Reputation: 4664
I'm trying to use the cooperative multiple inheritance pattern to resolve a problem. A very simplified version of my python 2.7 code looks like this:
class Base1(object):
def __init__(self, a, b):
self.a = a
self.b = b
def to_tuple(self):
return self.a, self.b
def to_string(self):
return '%s.%s' % self.to_tuple() # (1)
class Base2(object):
def __init__(self, c, d):
self.c = c
self.d = d
def to_tuple(self):
return self.c, self.d
def to_string(self):
return '%s-%s' % self.to_tuple() #(2)
class MyMixin(Base1, Base2):
def __init__(self, a, b, c, d):
Base1.__init__(self, a, b)
Base2.__init__(self, c, d)
def to_tuple(self):
return Base1.to_tuple(self) + Base2.to_tuple(self)
def to_string(self):
return '{}: {} '.format(Base1.to_string(self), Base2.to_string(self))
mix = MyMixin('a', 'b', 'c', 'd')
print(mix.to_string())
After writing this code, I was expecting the result:
a.b: c-d
but the code fails. When the line #(1)
is run, self
is a MyMixin
class, not a Base1
class, so to_tuple
returns 4 items.
The only way I've found to fix this is to replace the lines #(1)
and #(2)
above with:
return '%s.%s' % Base1.to_tuple() # (1)
return '%s.%s' % Base2.to_tuple() # (2)
and this feels terribly wrong for a number of reasons.
What am I doing wrong?
Upvotes: 1
Views: 232
Reputation: 3705
Here is what happens. When mix.to_string()
is called, first, it calls Base1.to_string(self)
passing a mix
instance as a self, which means when to_string is called on Base1 it has an instance of MyMixin
which returns ('a','b','c','d') on to_tuple
call. That's why it fails, cuz tuple contains 4 items and only 2 are required by line #1.
To solve this issue try to avoid inheritance from multiple classes with the same method signatures. Use composition instead.
class MyMixin(object):
def __init__(self, a, b, c, d):
self.base1 = Base1(a, b)
self.base2 = Base2(c, d)
def to_tuple(self):
return self.base1.to_tuple(self) + self.base2.to_tuple(self)
def to_string(self):
return '{}: {} '.format(self.base1.to_string(), self.base2.to_string())
Upvotes: 2