Abstract Classes
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.
aashish on Nov. 24, 2020
Excellent OOPS concept clearing session.
muondude on Jan. 13, 2022
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?
Bartosz Zaczyński RP Team on Jan. 14, 2022
@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?