I want to write abstract class that will force inheriting classes to implement all methods AND properties in my abstract class.
Additionally I want to use of setters and getters for my abstract property to make my code uncluttered and looking nicely
However, current implementation:
import abc
class Component(metaclass=abc.ABCMeta):
@property
@abc.abstractmethod
def status(self):
pass
@property
@status.setter
@abc.abstractmethod
def status(self, value):
pass
does enforce inheriting class to implement getter for my abstract property getter, but does not enforce creating a property setter (what is exactly what I want)
How can I achieve this behavior without loosing all benefits from application of further mentioned method (aka writing new methods and executing them in my abstract class setter) ?
The problem is that neither the getter nor the setter is a method of your abstract class; they are attributes of the property, which is a (non-callable) class attribute. Consider this equivalent definition:
Inheriting a property is quite different from inheriting a method. You are basically replacing the property, because your class itself does not have a reference to either the getter or the setter. Despite the name,
abstractmethod
does not actually make the property a method; it really does nothing more than add an attribute to whatever it is applied to and return the original value.So, to ensure that a subclass provides a read/write property, what are you to do? Skip the decorator syntax, define the getter and setter as explicit abstract methods, then define the property explicitly in terms of those private methods.
Or, you can make use of
__init_subclass__
(which postdatesabc
; its purpose is to allow class initialization that is otherwise only possible via a metaclass).This is actually an improvement over
abc
, in my opinion. If a subclass fails to define a read/writestatus
property, an exception will be raised when the class is defined, not just when you attempt to instantiate the class.