Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Controlling child class method from parent class

Let's say I have this code:

class Foo:
    def write(self, s=""):

        # Make sure that overwritten
        # 'write' method in child class
        # does what it's specified, and
        # then what comes next...

        print "-From Foo"

class Bar(Foo):
    def write(self, s=""):
        print s

baz = Bar()
baz.write("Hello, World!")

The last call obviously outputs the hello world by itself. I need to make it write the "-From Foo" as well, but without modifying the Bar class, just the Foo class. I've tried using the __bases__ and other stuff, but it won't work for my purpose.

like image 707
Daniel Watson Avatar asked Sep 06 '25 22:09

Daniel Watson


1 Answers

I 100% agree with Lattyware: you shouldn't do this. Parent classes shouldn't "know" about subclasses or how they work.

But I must say that it is possible using some __getattribute__ magic:

class Foo(object):
    def __getattribute__(self, attr):
        if attr != 'write':
            return super(Foo, self).__getattribute__(attr)
        meth = super(Foo, self).__getattribute__(attr)
        if meth.im_func is Foo.write.im_func:
            # subclass does not override the method
            return meth

        def assure_calls_base_class(*args, **kwargs):
            meth(*args, **kwargs)
            Foo.write(self, *args, **kwargs)
        return assure_calls_base_class

    def write(self, s=""):
        print "-From Foo"



class Bar(Foo):
    def write(self, s=""):
        print s

Running the code:

>>> b = Bar()
>>> b.write('Hello, World!')
Hello, World!
-From Foo

Note however that this is simply an hack, and will probably break when using a bit of inheritance, or even if you access write from the class:

>>> Bar.write(b, 'Hello, World!')  #should be equivalent to b.write('Hello, World!')
Hello, World!
like image 92
Bakuriu Avatar answered Sep 09 '25 19:09

Bakuriu