2017-04-21 7 views
1

問題を解決するために協調的な複数の継承パターンを使用しようとしています。協力的な複数継承とPython 2.7ミックスイン

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()) 

このコードを書いた後、私は期待していた結果:私のpython 2.7のコードの非常に単純化されたバージョンは、次のようになります

a.b: c-d 

が、コードは失敗します。行#(1)を実行した場合、はBase1クラスではなくMyMixinクラスであるため、to_tupleは4個のアイテムを返します。

私はこの問題を解決するために見つけた唯一の方法は、#(1)#(2)て上の行を置き換えることです:

return '%s.%s' % Base1.to_tuple() # (1) 
return '%s.%s' % Base2.to_tuple() # (2) 

を、これはいくつかの理由でひどく間違って感じています。

私は間違っていますか?

+0

Hrm。その周りには本当にクリーンな方法はありません。 'self.to_tuple()'は常にオーバーライドされたメソッドを呼び出します(つまり、すべてのメソッドが仮想です)。 "this * class *からメソッドを欲しい"と言う唯一の方法は、明示的にクラス名を指定することです。 – dhke

+0

この記事、おそらくあなたはPythonのアイデアの実装を誤解していたでしょう: http://www.artima.com/weblogs/viewpost.jsp?thread=281127 –

答えて

2

ここでは何が起こりますか。 mix.to_string()が呼び出されると、mixインスタンスを自己として渡すBase1.to_string(self)が呼び出されます。これは、to_stringがBase1で呼び出されたときに、MyMixinのインスタンスを持ち、( 'a'、 'b'、 'c'、 'd' )to_tupleに電話してください。それが失敗する理由は、cuzタプルには4つの項目が含まれ、行#1では2つだけが必要です。

この問題を解決するには、同じメソッドシグネチャを持つ複数のクラスからの継承を避けてください。代わりに合成を使用してください。

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())