Join us and get access to hundreds of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to hundreds of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Hint: You can adjust the default video playback speed in your account settings.
Hint: You can set the default subtitles language in your account settings.
Sorry! Looks like there’s an issue with video playback 🙁 This might be due to a temporary outage or because of a configuration issue with your browser. Please see our video player troubleshooting guide to resolve the issue.

Abstract Classes

Give Feedback

00:00 You’ve now built a basic program that can calculate the payrolls of various types of employees in a company. I’m going to put the UML diagram on the screen, and I want you to look at the four classes that we’ve created.

00:16 Are there any that we didn’t instantiate directly? Yes—that base Employee class at the very top. It’s only used to define .name and .id attributes, which get inherited by every other type of employee in our program.

00:34 But as of right now, nothing is stopping us from creating a generic Employee object, so let’s do that and pass it into the PayrollSystem. What could go wrong?

00:46 I’ll create a new Employee in our main program file with an id of 4 and a name of "Generic Employee".

00:57 Now, I’ll add this employee to the list and run the program again…

01:05 and this time we got an error. It’s saying that the generic Employee object is missing the .calculate_payroll() method that the PayrollSystem needs to calculate its payroll. That’s because that method is normally implemented by the specialized versions of Employee.

01:24 In other words, the Employee class does not conform to the IPayrollCalculator interface required by the PayrollSystem, so the whole thing breaks.

01:35 This isn’t actually a problem, though. The only reason our program broke is because we used it in a way it was not intended to be used. The Employee class exists just to be inherited from—not to be instantiated itself. That means it’s what’s called an abstract class.

01:56 We can’t instantiate it, but only inherit from it. In order to utilize a helpful abstract decorator,

02:05 we can import some special modules in the Python standard library. Let’s move back into our hr.py file, and at the top I’ll write from abc import ABC, abstractmethod.

02:25 Now I’m going to make the Employee class inherit from ABC, and I’ll create a new method called .calculate_payroll() so that this class conforms to the IPayrollCalculator interface. I’ll write pass in here to make it blank.

02:44 And I’ll add this little decorator @abstractmethod to mark this method as abstract. By inheriting from ABC and marking a method as abstract, we’ve told Python that this is an abstract class.

03:01 Now let’s see what happens when we move back to program.py and run it.

03:08 Now we’re getting a different error: Can't instantiate abstract class Employee with abstract methods calculate_payroll. This tells other developers two things.

03:20 One, they cannot instantiate the Employee class directly, and two, the Employee class can only be inherited from. When a class inherits from an abstract class, that class should either provide its own implementation for any of the methods in the parent marked as abstract, or it should become an abstract class in and of itself, leaving implementations of the parent’s abstract methods to its child classes.

03:52 In other words, it’s saying, “That implementation is not my problem, so I’m going to make my children implement it.” OOP really does model the real world. Anyway, all three specialized employee classes provide their own implementations of .calculate_payroll(), so all is good.

04:12 They inherit the abstract method and then provide their own implementation. Employee now conforms to the interface, but doesn’t actually implement the required .calculate_payroll() method.

04:26 Instead, it lets its children classes do that. If we were to simply remove the instantiation of the general Employee in our main program file and take it out to the list, everything would work perfectly fine. However, to more accurately follow the UML diagram from earlier, I’m going to remove everything about the Employee class that makes it abstract, including the .calculate_payroll() method.

04:56 Now, I’m going to move back into program.py and delete the generic_employee object.

05:07 And it looks like everything still works.

Become a Member to join the conversation.