I'm trying to understand abstract classes. If a User base class has fully implemented methods and is meant to be extended by Student and Professor, can it still be abstract? How does this work in Python?
Does an abstract class need an abstract method?
Answers
There are two separate ideas here. You can design User as a base class that nobody should instantiate, but whether the language actually prevents that depends on its rules.
In Python, inheriting from ABC alone doesn't prevent instantiation. The class needs an unimplemented abstract method, usually declared with the abstractmethod decorator, for the ABC machinery to block it. A subclass becomes instantiable once it implements all inherited abstract methods.
So if User has no abstract methods, Python will let you create a User. You can still document that it's intended as a base class, but that intention isn't enforced by ABC alone.
Reply to this answer
The answer changes with the language. Java and C# let you declare a class abstract even if all its methods are implemented. In C++, a class is abstract when it has at least one pure virtual function that hasn't been overridden.
That distinction is why an explanation of abstract classes in general doesn't necessarily tell you what Python will enforce.
Reply to this answer
Think of an abstract method as a requirement for subclasses, not just a switch to stop someone creating the base class. For example, if every kind of User needs a role description but Student and Professor provide it differently, that could be an abstract method.
The base class can still hold shared data and implemented behavior. It doesn't have to be a collection of empty method declarations.
++fresh!from~revision:
If there isn't any behavior that subclasses need to provide, I'd be wary of inventing an abstract method just to prevent instantiation.
Reply to this answer
Add your answer
Answers are reviewed before publication.
buffering in slippers:
So inheriting from ABC marks the class for the mechanism, but doesn't make it non-instantiable by itself?
~perhaps!try+sideB:
Right. The instantiation check depends on whether the class has any abstract methods left unimplemented.