Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cooperative multiple inheritance issue

This is an extension to this question and raises a problem, which you, my fellow StackOverflowers, will hopefully be able to help me with. From the referenced question, consider the final code sample:

class A(object):
    def __init__(self):
        print "entering A"
        print "leaving A"

class B(object):
    def __init__(self):
        print "entering B"
        super(B, self).__init__()
        print "leaving B"

class C(A,B):
    def __init__(self):
        print "entering c"
        super(C, self).__init__()
        print "leaving c"

As noted by the poster, when initialising C, the __init__ for B is never called. On considering Raymond Hettinger's post, the code for class A should be modified to also call super().__init__():

class A(object):
    def __init__(self):
        print "entering A"
        super(A, self).__init__()
        print "leaving A"

We're all good so far. However, what if our class' __init__ functions accept arguments? Let's assume that all the __init__ functions accept a single argument and for consistency, we'll simply call it foo, the code is now:

class A(object):
    def __init__(self, foo):
        print "entering A"
        super(A, self).__init__(foo)
        print "leaving A"

class B(object):
    def __init__(self, foo):
        print "entering B"
        super(B, self).__init__(foo)
        print "leaving B"

class C(A,B):
    def __init__(self, foo):
        print "entering c"
        super(C, self).__init__(foo)
        print "leaving c"

Here we hit a snag. When initialising any of the classes A, B or C, we eventually call object.__init__ with a single argument, foo, which errors with TypeError: object.__init__() takes no parameters. However, to remove one of the super().__init__ functions would mean the classes are no longer cooperative in the case of multiple inheritance.

After all that, my question is how does one get around this problem? It appears that multiple inheritance is broken in anything but cases where no arguments are passed to the __init__ functions.

UPDATE:

Rob in the comments suggests stripping keyword arguments (referenced in Raymond H's post). This actually works very well in the case of multiple inheritance until your change you code. If one of your functions no longer uses one of the keyword arguments and ceases to strip it without modifying the calling function, You will still receive the TypeError noted above. As such, this seems like a fragile solution for large projects.

like image 432
Endophage Avatar asked Apr 30 '13 16:04

Endophage


People also ask

Does the order of inheritance matter in multiple inheritance?

In multiple inheritances, the methods are executed based on the order specified while inheriting the classes.

Why Multiple inheritance is not possible in Ruby?

In Ruby, single class inheritance is supported, which means that one class can inherit from the other class, but it can't inherit from two super classes. In order to achieve multiple inheritance, Ruby provides something called mixins that one can make use of.

Does Ruby support multiple inheritance?

Ruby supports only single class inheritance, it does not support multiple class inheritance but it supports mixins.


1 Answers

Admittedly, this solution may not be the most pythonic or ideal, but creating a wrapper class for object like so allows you to pass arguments around each __init__ in the inheritance:

class Object(object):
    def __init__(self,*args,**kwargs):
        super(Object,self).__init__()

class A(Object):
    def __init__(self,*args,**kwargs):
        super(A,self).__init__(*args,**kwargs)

class B(Object):
    def __init__(self,*args,**kwargs):
        super(B,self).__init__(*args,**kwargs)

class C(A,B):
    def __init__(self,*args,**kwargs):
        super(C,self).__init__(*args,**kwargs)
like image 188
ievans3024 Avatar answered Oct 02 '22 08:10

ievans3024