I dont know where I'm going wrong trying to create an object in a subclass through inputs

Viewed 44

I've tried many different things so it's a little all over the place, please help I've been able to make the first class and then in a different file create some objects for it, but for this subclass I need to use user input and I just can't figure it out.

I have made it so the shift input has to be a 1 or 2 for a day or night shift, I just don't have the knowledge for this.

class Employee:
    def __init__(self, name, id, dept, title):
        self.__name = name
        self.__id = id
        self.__dept = dept
        self.__title = title

    def get_name(self):
        return self.__name

    def get_id(self):
        return self.__id

    def get_dept(self):
        return self.__dept

    def get_title(self):
        return self.__title

    def __str__(self):
        result = ""
        result += "Name: " + self.get_name() + "\tID Number: " + str(self.get_id()) + \
                  "\tDepartment: " + self.get_dept() + "\tJob Title:" + self.get_title()
        return result


class ShiftEmployee(Employee):
    def __init__(self, name, id, dept, title, shift, pay):
        Employee.__init__(self, name, id, dept, title)
        self.__shift = shift
        self.__pay = pay

    @classmethod
    def inputs(self):
        self.__name = input("Enter name: ")
        self.__id = input("Enter ID number: ")
        self.__dept = input("Enter department: ")
        self.__title = input("Enter Jobe title: ")
        self.__shift = input("Enter shift: ")
        self.__pay = input("Enter hourly pay: ")
            #set_shift(self, shift):
        #self.__shift = shift

    #def set_pay(self, pay):
        #self.__pay = pay

    def get_shift(self, shift):
        if self.__shift == 1:
            return "Day"
        elif self.__shift == 0:
            return "Night"
        else:
            return "Invalid entry"

    def get_pay(self, pay):
        return self.__pay

    def __str__(self):
        result = ""
        #result += Employee.__str__(self)
        result += "Name: " + self.get_name(ShiftEmployee) + "\tID Number: " + str(self.get_id(ShiftEmployee)) + \
                  "\tDepartment: " + self.get_dept(ShiftEmployee) + "\tJob Title:" + self.get_title(ShiftEmployee) + \
                  "\tShift: " + self.get_shift(ShiftEmployee) + "\tHourly Pay: " + str(self.get_pay(ShiftEmployee))
        return result


shift_emp = ShiftEmployee
shift_emp.inputs()
print(shift_emp.__str__(ShiftEmployee))
2 Answers
  1. Don't use a classmethod because

A class method is a method that’s shared among all objects.

Though python itself does not force this behavior, your use of self in the inputs definition indicates that you are not doing what you think. the parameter is traditionally named cls in @classmethod-annotated methods, because the object you're referring to inside the body is not an instance of the class, but the class object itself. This means if you have multiple ShiftEmployee objects, they're going to be writing their data to the same variables. This is not what you want to happen.

  1. you are not instantiating a ShiftEmployee object with shift_emp = ShiftEmployee, but rather assigning the class to the variable shift_emp, which is not what you want to do. so if you remove the @classmethod annotation, I think what you want is
shift_emp = ShiftEmployee() # __init__ gets called when you use this constructor invocation
shift_emp.inputs()
print(shift_emp)
  1. Your __str__ methods don't make a lot of sense. You are passing the class object to each getter, which doesn't seem like it's what you'd want to do. The class object defines the class, what you want are the instances of the class. It's an important, if initially confusing distinction. Posting the error you get would help, but here's what I would expect the methods to look like. I'm not using the getters, because this is internal access, but you can use them instead of directly referring to the state variables if you prefer.
# Employee
def __str__(self):
   return f"Name: {self.__name}   ID Number: {self.__id}   Department: {self.__dept}     Job Title: {self.__title}"

# ShiftEmployee
def __str__(self):
    return super(ShiftEmployee, self).__str__() + f"    Shift: {self.__shift}    Hourly Pay: {self.__pay}"

So what's going on here? For one thing, we use format strings because they are easier to work with and exactly the thing you wanted. Then we're using the superclass (Employee) to provide the shared functionality, and using the descendent class to enrich with the ShiftEmployee-only data. I skipped the accessor methods because they're redundant when accessing "private" data from inside the class members. Note that this won't quite do what you expect, either, w.r.t. the shift value that gets printed -- it's going to print the int, not "Night" or "Day". This is where your accessor method comes into play, except that your accessor has an extraneous parameter, shift. So you'd have to remove that value.

Please use the following way to initialize the class and printing the class,

shift_emp = ShiftEmployee() # Added Parenthesis
shift_emp.inputs()
print(str(shift_emp)) # Pass class object to inbuilt str() method to get output from __str__() method from class
Related