2012-02-22 7 views
2

私は自分自身がダイヤモンド継承の奇妙な状況にあることを知っています。さらに悪いことに、ダイヤモンドの中間のクラスがメンバを共有しています。下に私の問題を強調するコードの断片を示しました。pythonとsuperで同じメンバでクラスを継承する

出力

z : None 

に問題を与え、私は組み込み関数super

class A(object): 
    pass 

class B(A): 
    def __init__(self, z=None, **kwargs): 
     self.z = z 
     super(B, self).__init__(**kwargs) 
     # super(B, self).__init__(z=z, **kwargs) 

class C(A): 
    def __init__(self, z=None, **kwargs): 
     self.z = z 
     super(C, self).__init__(**kwargs) 

class D(B, C): 
    pass 

d = D(z='y') 

for arg, value in d.__dict__.iteritems(): 
    print arg, ':', value 

のためのPythonドキュメントサイトにリンクされている私はhttp://rhettinger.wordpress.com/2011/05/26/super-considered-super/から学んだライティングのクラスで使用する方法関数の一致の署名がクラスCのinit呼び出しからz引数を取り除くことを保証するためにキーワード引数を使用する方法です。引数を強制的にkwargsに追加することができますが(コメント付きコードを参照)、これはB型のオブジェクトをインスタンス化することができません。これはパラメータを取らないオブジェクトのinitを呼び出すことになります。これは、以下のオブジェクトのいずれかをインスタンス化する際に無効な引数を入れないためです。

また、変数を設定する前にスーパーがあると、最高レベルのオブジェクトが下位レベルを上書きするため、問題が修正されています。しかし、実際の "設定"はすべて低レベルのクラスで実行され、高レベルのクラスは継承の連鎖を設定する値を渡すので、私のコードは大まかに構築されています。親コールにどこに適合するかについてのガイドラインはありますか?

任意のアイデアStackoverflow?

ありがとう

p.s.これはちょうど「協同組合」の悪いデザインですか?協同組合のクラスとは何ですか?従うべき規則やガイドラインはありますか?

編集:

StackOverflowのは、私は自分の質問に答えることはできませんが、私は解決策を考え出しました。

私は、協調クラス間で共有メンバーが存在するはずはないと思います。これまでに、互いに独立した2つのクラスがある場合(つまり、ある種の関係です)、メンバーを共有する場合、継承関係に抽象レベルを追加する必要があります。

共有メンバーを取り出し、共有ベースクラスから継承し、ダイヤモンドのクラスによってから継承されている別のクラスに入れなければなりません。

以下は修正されたコードです。 OP内のリンクを踏まえて、私は(私が推測ここで最もように)私は間違った用語を使用する場合、私は謝罪ので、私は正式なプログラミング教育を受けていない指摘しなければならないルートベースクラス

を導入しました。

class Root(object): 
    pass 

class A(Root): 
    pass 

class HasAZ(Root): 
    def __init__(self, z=None, **kwargs): 
     self.z = z 
     super(HasAZ, self).__init__(**kwargs) 

class B(HasAZ, A): 
    pass 


class C(HasAZ, A): 
    pass 

class D(B, C): 
    pass 

d = D(z='y') 

for arg, value in d.__dict__.iteritems(): 
    print arg, ':', value 
+0

多重継承を使用しないでください彼らがメンバーを共有しているという事実。彼らがメンバーを共有している場合は、他の何かを共有する必要があります。メンバーを連れて共通のクラスに引き出すことはできませんか? –

+1

ありがとう、それは私が最後にしたものです。私は明らかに私のオブジェクト指向の思考プロセスに取り組む必要があります – scruffyDog

+0

私はそれが最高のためだと思っています=) –

答えて

1

たぶんそこにそれを行うには良い方法があるが、これは上書きを避ける必要があります::

class C(A): 
    def __init__(self, z=None, **kwargs): 
     if not hasattr(self, 'z'): 
      self.z = z 
     super(C, self).__init__(**kwargs) 
+0

おかげで、hasattrや文字列を使ってメンバーを取得することに頼っていることから離れようとしました。また、私は言及しませんでしたが、私はコードの中で後でメソッドを上書きできるようにする必要がある__init__で多くのsetメソッドを使用します – scruffyDog

1

が、これは「協同組合のクラス」のちょうど悪いデザインですか?

はい、特に属性衝突のためです。同じ名前の属性を持たない場合は、これまで問題にはならないでしょう。B.zは、C.zによって上書きされません。

協力的なクラスとは何ですか?ルールまたはガイドラインに従うべきことはありますか?すでに読ん

1:

http://rhettinger.wordpress.com/2011/05/26/super-considered-super/

は、私の知る限りでは、それは協力的なクラスのためのルール/ガイドラインのための最高のソースです。

あなたは選択することができます。次のことができます。

  • 継承ツリー内のすべてのクラス全体でユニークなあなたの属性名

または

  • は常にツリーの下のすべての引数を渡す作ります。その時点で、あなたにも__init__(self, **kwargs)

または

  • にすべての署名を変更する場合があります与え、私はあなたがその仕事を作ることができるか見ることができません
関連する問題