私はひし形の継承という奇妙な状況に陥っています。さらに悪いことに、ひし形の真ん中にあるクラスがメンバーを共有しています。以下に、私の問題を強調するコードの切り詰めを示しました。
組み込み関数の python ドキュメント サイトにリンクされているhttp://rhettinger.wordpress.com/2011/05/26/super-considered-super/から学んだクラスの作成に使用した方法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
出力を与える
z : None
問題は、キーワード引数を使用して関数のシグネチャが一致することを確認する方法が、クラス C の init 呼び出しから z 引数を奪うことです。引数を kwargs に強制的に追加することはできますが (コメント付きのコードを参照)、これにより、型 B のオブジェクトをインスタンス化できなくなります。これは、パラメーターを取らないオブジェクトの init への呼び出しになるためです。以下のオブジェクトのいずれかをインスタンス化するときに無効な引数を入れるのを防ぐため、素晴らしい機能です。
また、変数を設定する前にスーパー行があると、最高レベルのオブジェクトが下位レベルを上書きするため、問題が修正されることに気付きました。ただし、実際のすべての「設定」は下位レベルのクラスによって実行され、上位レベルのクラスは継承のチェーンに設定される値を渡すため、私のコードは最後にスーパーを中心に構築されています。親の呼び出しのどこに収まるかについてのガイドラインはありますか?
何かアイデアはありますか?
ありがとう
ps これは「共同クラス」の設計が悪いだけですか? 協力クラスとは正確には何ですか?従うべき規則やガイドラインはありますか?
編集:
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