Force the implementation of a certain type of abstract method

Asked

Viewed 132 times

0

In the Python it is possible to define classes abstratas and métodos abstratos slightly simply, for example:

class Spam(ABC):

    @abstractmethod
    def grok(self):
        pass

This class cannot be instantiated because it has the method grok is explicitly defined as abstract, this class must be extended and then superscripted this method, follows an example of my doubt:

class Spam(ABC):

    @staticmethod
    @abstractmethod
    def grok():
        pass


class Derived(Spam):

    def grok(self):
        pass

As I said before this class should be extended and then overwritten the method grok, but note that this time the method besides being abstract defines that it is also static, but as you can see nothing forces me to have to define it as static, only that I must define it-Ló. My question is: Como posso obrigar a implementação do método com seu tipo previamente definido na classe base abstrata?

  • And does it make sense for a static method to be abstract? Because it is static it will belong only to the class, so why inherit it it abstractly? What’s the point in doing this?

  • I saw a video on the Internet that guy created a basic abstraction of a Pizza and had a static method called ingredientes, that returned the ingredients of the same. This method should be overwritten in the base classes so he made it abstrato, but as I said nothing requires that the same be implemented being estático.

  • https://www.giacomodebidda.com/factory-method-and-abstract-factory-in-python/

1 answer

3


Checks and transformations on the methods and attributes of a class at the time they are created can be done in three different ways in Python: with the use of a metaclass implementing the method __new__ or __init__, with the method __init_subclass__ in the body of a base class, or using class decorators.

An approach via decorators require them to be used in each class of their hierarchy - the decorator is not "inherited". __init_subclass__ may be legal in some cases, but will mix code in your Base class. If there is more than one base class in your project, you will both have to have the __init_subclass__ - you would have to do a mixin for the base classes - so it might complicate more. The mechanism that checks abstract methods of ABC uses metaclasses - and it may be more natural to inherit the metaclass of ABC and expand the checks made.

In this case, checking is also not so trivial - if you want to use the default Python marker @staticmethod will have to check in the base class if the method exists there - and exists as Static, and then raise an exception. (In the documentation there is even a @abstractstaticmethod but it is obsolete - the recommendation is to use the two decorators as in his same example (abstractmethod as the innermost decorator)

Another detail is that the Python ABC only of abstract method error not reset when the class is instantiated, not when it is declared - for static and class methods, this check does not help, since it can be used without an instance of the class.

So the thing is to actually write a metaclass extending abc.ABCMeta to carry out the checks on __init__. This check has to include checking all superclasses to see if there are any __abstractmethod__, check whether or not he was overrided in the final class, and check whether he was a staticmethod: in Python, static methods are indistinguishable from function, so you have to retrieve the method from the dictionary of the class where it is set and check with isinstance(cls.__dict__["method_name"], staticmethod).

But it’s a little more complex than that - because if you have a base class with the abstract methods "A", a subclass "B" that implements the abstract methods, and another subclass C that inherits from "B", you have to get to the dictionary of the class "B" when checking the static methods in class C. This is possible with the use of the attribute __qualname__ in the methods, but it is not so trivial.

As you can see, there are many corner cases - it’s really worth wondering if you need this mechanism as it is. It can be done, but it’s a component of a complex framework, and it goes against the philosophy of language, where you have to let things be stated, document what you need, and make an execution-time mistake if something hasn’t been done right. Of course it is understandable that there are times when this is not desirable - so much so that in recent years the mechanisms of indication of typing with Typing and mypy have evolved a lot.

I can write this metaclass, since I leave it here and in the gist of Github and it is available for the future - just confirm that you really need it, please.

  • By the way - I saw in the comments that you are learning about OO in Python and found interesting the static method for "ingredients" of Pizza - as you saw in the answer, this is possible, but far away to be recommended - static methods are actually very little used in Python. Even the mechanism of abstract methods is little used, because the real solutions made in the language really don’t need it - it’s something very different from a static language.

  • A use case for this would only be in a large system, with several developers that will define the concrete classes, and that would require almost the creation of an intermediate framework to minimize errors in implementations - this after the architecture of the whole system is very well thought out. To follow examples of OOP with didactic classes of Pizza flavors, or pets, it is better to assume that this is not a feature available in Python.

  • I am studying the language in depth because I find it spectacular, if I could I would like to see how it would look this implementation you explained, but if it is something that will harm your time, do not need, I thank you in the same way.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.