4

This is sort of an add-on question in reference to the very popular super( ) question. The question was basically "Why should I use super( )" and the answer was "Because you don't have to reference the parent class, which can be nice."

My question is...why in the world is that a good thing? Whatever happened to "Explicit is better than implicit?" Let's say I'm reading some other developer's code and I see:

class Foo(Bar, Baz):
    def my_method(self):
        super(Foo, self).who_knows( ) #nobody knows!

I now have to dig through the docs on Bar and Baz and all of their parent classes all the way up the tree to find out where who_knows( ) is being called from and what it does. I also need a perfect understanding of the Method Resolution Order in order to know which who_knows( ) is actually being called.

Now let's look at the same code without super( ):

class Foo(Bar, Baz):
    def my_method(self):
        Baz.who_knows(self) #ah, Baz knows

Much clearer, no guesswork or understanding of the MRO required.

I'm not raising this question to start an argument or a philosophical discussion. I'm just hoping that someone can show me some very clear examples in which the implicit nature of super( ) is actually desirable because honestly I'm not seeing it.

Community
  • 1
  • 1
galarant
  • 1,959
  • 19
  • 24
  • 3
    http://rhettinger.wordpress.com/2011/05/26/super-considered-super/ – Martijn Pieters Jan 18 '14 at 23:46
  • Because cooperative base classes can make your life easier. – Martijn Pieters Jan 18 '14 at 23:46
  • @MartijnPieters at the expense of anyone else reading your code? – galarant Jan 18 '14 at 23:49
  • @galarant Some people don't even understand polymorphism at all. Should we stop using this mechanism also? – BartoszKP Jan 19 '14 at 00:00
  • @BartoszKP I don't think that's a good analogy because polymorphic operations will raise an Exception (hopefully a useful one) if you send them an object that does not support the operator. That's perfectly explicit and perfectly fine. – galarant Jan 19 '14 at 00:09
  • 2
    "I now have to dig through the docs on Bar and Baz and all of their parent classes all the way up the tree to find out where who_knows( ) is being called from and what it does." - actually, in cooperative multiple inheritance, you can't do that. You have no idea which method is the next method in the MRO. I believe the idea is that you're supposed to design the methods so that it only matters that they're called in an order induced by a valid topological sort of the inheritance graph. What this would look like in a real program, I don't know; I try to avoid complex inheritance. – user2357112 Jan 19 '14 at 00:11

2 Answers2

2

For this case specifically, super(Foo, self).who_knows() is not a good thing at all. I would just do self.who_knows().

super() is commonly used when overriding the method with the same name from parent class.

Xuan
  • 5,255
  • 1
  • 34
  • 30
1

When you are delegating implementations to other parts of code, being "explicit" about how that code is written defeats the purpose. Knowing exactly what is being called equates to having a dependency on that implementation so that if one piece of code changes the other must change also.

Consider that the problem of ambiguity still exists with the old Baz.who_knows(self) method. If Baz does not override who_knows, then you still don't know which of Baz's superclasses define the actual implementation. So do you change that line in Foo's code to point to the class that actually implements it? But if you then do decide to override it in Baz, you need to update Foo again (as well as all other subclasses).

nmclean
  • 7,564
  • 2
  • 28
  • 37