0

Basically, the problem I have is asked here and there are some answers, like below, where Son does some stuff like Father (the init in this case) and some other stuff like GrandFather (do_thing).

class GrandFather(object):
    def __init__(self):
        pass

    def do_thing(self):
        # stuff

class Father(GrandFather):
    def __init__(self):
        super(Father, self).__init__()

    def do_thing(self):
        # stuff different than Grandfather stuff

class Son(Father):
    def __init__(self):
        super(Son, self).__init__()

    def do_thing(self):
        super(Father, self).do_thing()  # <-- this line bypasses Father's implementation

What I am wondering is if there are any consequences to calling super like that (the last line above), i.e., passing a class type other than your own. I mean something like your code breaking at some weird point where you don't expect it.

Community
  • 1
  • 1
Mahdi
  • 1,646
  • 19
  • 30
  • What is not already covered [here](http://stackoverflow.com/questions/5033903/python-super-method-and-calling-alternatives), [here](http://stackoverflow.com/questions/222877/what-does-super-do-in-python) or [here](http://stackoverflow.com/questions/576169/understanding-python-super-with-init-methods)? – Stephen Rauch Feb 20 '17 at 17:40
  • 1
    @StephenRauch what is not covered? My question is not covered! :D Notice that the last line in my example reads `super(Father, self)` rather than `super(Son, self)`. The latter is the normal way to use `super` and this is covered in the links you provided. My question is however about the former, where I bypass the direct parent class, and call the method in the grandparent class! – Mahdi Feb 21 '17 at 20:09

1 Answers1

0

What you're asking about will generally work, but it may not do exactly what you intend in the presence of multiple inheritance. For instance, if Son also inherited from a Mother class (which due to incest was also a subclass of Grandfather), you'd not get the call you expected from your last line:

class GrandFather(object):
    def do_thing(self):
        print("Grandfather")

class Father(GrandFather):
    def do_thing(self):
        print("Father")

class Mother(GrandFather):
    def do_thing(self):
        print("Mother")

class Son(Father, Mother):
    def do_thing(self):
        super(Father, self).do_thing() # will print "Mother", not "Grandfather"

This issue could even crop up unexpectedly if the multiple inheritance was added in a Son subclass (e.g. class GrandSon(Son, Mother): pass with your previous definition of Son only inheriting from Father).

This may or may not be what you want. If you want to get GrandFather's implementation of do_thing all the time, you should explicitly call GrandFather.do_thing(self), rather than trying to use super.

But it's not generally a good idea to have classes bypassing their parents methods. You will probably be better served by reorganizing your code so it is not needed. Perhaps you could factor out the parts of GrandFather.do_thing that you want Son to be able to use into a separate method. You wouldn't need to override that method in Father, you could just not call it from Father.do_thing.

Blckknght
  • 85,872
  • 10
  • 104
  • 150