Search code examples
pythonpolymorphismsubclasspython-decoratorsmetaclass

Forcing overriden method to call base method implementation


class Base:
    def method(self):
        print("Base method called")

class Derived(Base):
    def method(self):
        print("Derived method called")

I would like to find a way for the derived method to call the base method implementation automatically,or better yet, to force the calling of the base method before the derived method is called.

ex:

derived = Derived()
derived.method()

desired output:

Base method called
Derived method called

I wanted to avoid explicitly calling the base method inside the derived method.

I tried messing with __init_subclass__ hacks:

class Base:
    def __init_sublcass__(cls, *args, **kwargs):
        def wrapper(self):
            super().method()
            self.method()
        cls.method = wrapper
    
    def method(self):
        print("Base method called")

It works but pylance has problems with it and it's not really ideal or easy to understand.


Solution

  • I think you might force the method() to always call Base.method() using a metaclass.

    How about something like:

    class Base_Meta(type):
        def __init__(cls, name, bases, dct):
            def method_new(self):
                Base.method(self)
                cls.method_old(self)
    
            if cls.__name__ != "Base":
                cls.method_old = cls.method
                cls.method = method_new
    
    class Base(metaclass=Base_Meta):
        def method(self):
            print("Base method called")
    
    class Derived(Base):
        def method(self):
            print("Derived method called")
    
    d = Derived()
    d.method()
    

    I think that will give you:

    Base method called
    Derived method called