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.
Are there any that we didn’t instantiate directly? Yes—that base
Employee class at the very top. It’s only used to define
.id attributes, which get inherited by every other type of employee in our program.
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?
I’ll create a new
Employee in our main
program file with an
4 and a
00:57 Now, I’ll add this employee to the list and run the program again…
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
In other words, the
Employee class does not conform to the
IPayrollCalculator interface required by the
PayrollSystem, so the whole thing breaks.
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,
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.
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.
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.
Now let’s see what happens when we move back to
program.py and run it.
Now we’re getting a different error:
Can't instantiate abstract class Employee with abstract methods calculate_payroll. This tells other developers two things.
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.
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.
They inherit the abstract method and then provide their own implementation.
Employee now conforms to the interface, but doesn’t actually implement the required
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
Now, I’m going to move back into
program.py and delete the
Excellent OOPS concept clearing session.
I followed this up until you introduced “abc” and “ABC”. That really confused me. These don’t exist right? So is this needed to declare an abstractmethod in the Employee class? This isn’t needed for you code to function, but is having this abstract method in the parent class good SW engineering to let others know they need to create this method?
@muondude The point of an abstract type is code reuse. Since you can’t instantiate an abstract class, its only purpose is for other classes to extend it or inherit from it. It lets you encapsulate the least common denominator and build subclasses on top of it.
Become a Member to join the conversation.
Dan B on Nov. 13, 2020
So what’s the point?