Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Super deal with multiple inheritance?

When inheriting from two objects like these

class Foo(object):
  def __init__(self,a):
    self.a=a

class Bar(object):
  def __init__(self,b):
    self.b=b

I would normally do something like this

class FooBar(Foo,Bar):
  def __init__(self,a,b):
    Foo.__init__(self,a)
    Bar.__init__(self,b)

How does super know if I want to call both? and if so how will it know which argument to pass where. Or is it simply not possible to user super here?

Even if Foo and Bar take the same arguments can super deal with this?

Or should I not be trying to do this kind of this in the first place?

like image 264
GP89 Avatar asked Oct 26 '11 13:10

GP89


People also ask

Who supports multiple inheritance?

The Java programming language supports multiple inheritance of type, which is the ability of a class to implement more than one interface. An object can have multiple types: the type of its own class and the types of all the interfaces that the class implements.

Can we use super in multiple inheritance in Python?

Supercharge Your Classes With Python super()Python supports inheritance from multiple classes.

What is the problem with multiple inheritance?

Multiple inheritance has been a controversial issue for many years, with opponents pointing to its increased complexity and ambiguity in situations such as the "diamond problem", where it may be ambiguous as to which parent class a particular feature is inherited from if more than one parent class implements said ...

Can a class be inherited from more than one super class?

Multiple Inheritance is a feature of an object-oriented concept, where a class can inherit properties of more than one parent class.


1 Answers

Using super(), __init__() and multiple inheritance is a bit tricky.

In the normal flow of things, every method calls super(), with the classes that inherit only from object doing a little extra work to make sure that the method actually exists: it'll look a bit like this:

>>> class Foo(object):
...     def frob(self, arg):
...         print "Foo.frob"
...         if hasattr(super(Foo, self), 'frob'):
...             super(Foo, self).frob(arg)
... 
>>> class Bar(object):
...     def frob(self, arg):
...         print "Bar.frob"
...         if hasattr(super(Bar, self), 'frob'):
...             super(Bar, self).frob(arg)
... 
>>> class Baz(Foo, Bar):
...     def frob(self, arg):
...         print "Baz.frob"
...         super(Baz, self).frob(arg)
... 
>>> b = Baz()
>>> b.frob(1)
Baz.frob
Foo.frob
Bar.frob
>>> 

But when you try to do something similar on a method that object actually has, things get a little dicey; object.__init__ doesn't take arguments, so about the only safe way to use it is to call super().__init__() with no arguments, since that call might be handled by object.__init__. But then it might not be handled by object.__init__, and instead handled by a class elsewhere in the inheritance graph. Thus any class which defines __init__ in a multiple inheritance class heirarchy must be prepared to be called with no arguments.

one way of dealing with this is to never use arguments in __init__(). Do minimal initialization, and rely on setting properties or using other means to configure the new object before use. That's pretty unpleasant, though.

Another way is to use only keyword arguments, something like def __init__(self, **keywords): and always remove the arguments that apply to the given constructor. This is a hope based strategy, you hope that all of the keywords get consumed before control reaches object.__init__.

A third way is to define a superclass to all of the multiple-inheritable bases which itself defines __init__ in some useful way and does not call super().__init__ (object.__init__ is a no-op anyway). This means you can be sure that this method is always called last, and you can do whetever you like with your arguments.

like image 164
SingleNegationElimination Avatar answered Oct 26 '22 12:10

SingleNegationElimination