Given a 'contract' of sorts that I want to implement, I want the code to
- tell the reader what the intent is
- allow the type checker to correct me (fragile base class problem)
E.g. in C++, you can
class X: public Somethingable {
int get_something() const override
{ return 10; }
};
Now when I rename Somethingable::get_something (to plain something for instance), the compiler will error on my X::get_something because it is not an override (anymore).
In C# the reader gets even more information:
class X : Somethingable {
int GetSomething() implements Somethingable.GetSomething { return 10; }
}
In Python, we can use abc.ABC and @abstractmethod to annotate that subclasses have to define this and that member, but is there a standardised way to annotate this relation on the implementation site?
class X(Somethingable):
@typing.implements(Somethingable.get_something) # does not exist
def get_something(self):
return 10
I was overestimating the complexity of such solution, it is shorter:
overridedecorator can mark overriding methods, andInterfaceMetaconfirms that these methods do exist in superclass._check_lspis the most complex part of this, I'll explain it below.What is actually going on? First, we take a callable and add an attribute to it from the decorator. Then metaclass looks for methods with this marker and:
propertyremains property,classmethodremainsclassmethodandstaticmethodremainsstaticmethodUsage
This warns:
You can set the metaclass on
Fooas well with the same result.LSP
LSP (Liskov substitution principle) is a very important concept that, in particular, postulates that any parent class can be substituted with any child class without interface incompatibilities.
_check_lspperforms only the very simple checking, ignoring type annotations (it ismypyarea, I won't touch it!). It confirms that*argsand**kwargsdo not disappearImplementation follows: