1

は、次のPythonコードを考えてみましょう:孫でsuper機能を実行する場合解決ダイアモンド継承

class Parent(object): 
    def __init__(self, name, serial_number): 
     self.name = name 
     self.serial_number = serial_number 


class ChildA(Parent): 
    def __init__(self, name, serial_number): 
     self.name = name 
     self.serial_number = serial_number 
     super(ChildA, self).__init__(name = self.name, serial_number = self.serial_number) 

    def speak(self): 
     print("I am from Child A") 


class ChildB(Parent): 
    def __init__(self, name, serial_number): 
     self.name = name 
     self.serial_number = serial_number 
     super(ChildB, self).__init__(name = self.name, serial_number = self.serial_number) 

    def speak(self): 
     print("I am from Child B") 


class GrandChild(ChildA, ChildB): 
    def __init__(self, a_name, b_name, a_serial_number, b_serial_number): 
     self.a_name = a_name 
     self.b_name = b_name 
     self.a_serial_number = a_serial_number 
     self.b_serial_number = b_serial_number 
     super(GrandChild, self).__init_(something) 

、ChildAとChildBは両方正しい引数を取得するよう__init__引数をフォーマットする適切な方法は何ですか?

また、GrandChildクラス内からspeakメソッド(ChildAのバージョンとChildBのバージョン)の2つの異なるバージョンにアクセスするにはどうすればよいですか?この方法を呼び出すときに明示的にselfを配置する必要があり

ChildA.__init__(self, a_name, a_serial) 
ChildB.__init__(self, b_name, b_serial) 

注:

+1

これは多重継承の有効なユースケースのようには思えません。代わりに合成を使用してみませんか? – MSeifert

答えて

0

あなたはスーパーが__mro__プロパティを以下のため、子Aの__init__メソッドが呼び出されます、孫からスーパーを呼び出すときに、(親が左から右、次に左から右への祖父母、そして偉大な祖父母、...)

もスーパーコールを呼び出すので、すべてのスーパーコールが連鎖され、子bの__init__と親initが呼び出されます。

これが機能するには、インターフェイスは一般的に一貫性が必要です。それは、位置的な議論は同じことを意味する必要があり、順序にある​​必要があります。

そうでない状況では、キーワードの引数がうまくいく場合があります。

class parent: 

    def __init(self, name, serial, **kwargs): 
     self.name = name 
     self.serial = serial 

class ChildA(parent): 

    def __init__(self, a_name, a_serial, **kwargs): 
     self.a_name = a_name 
     self.a_serial = a_serial 
     super().__init__(**kwargs) 

class ChildB(Parent): 

    def __init__(self, b_name, b_serial, **kwargs): 
     self.b_name = b_name 
     self.b_serial = b_serial 
     super().__init__(**kwargs) 


class GrandChild(ChildA, ChildB): 
    def __init__(self): 
     super().__init__(name = "blah", a_name = "a blah", b_name = "b blah", a_serial = 99, b_serial = 99, serial = 30) 

また、コード名とシリアルはすべてのクラス間でインスタンスプロパティとして再利用されますが、それはおそらくあなたが望むものではないことに注意してください。

0

Pythonでは、明示的に特定のメソッド(の1)あなたの親クラス(ES)を呼び出しcan

また、あなたが行ったように、super()の方法を使用することもできます。これは「最初の」親と呼ばれます。正確な順序は動的ですが、デフォルトでは、継承階層の左から右、深さ優先、事前注文scansです。したがって、super()コールは、ChildA__init__とのみ電話します。

+0

GrandChildクラスでsuperを呼び出すと、ChildAとChildBの__init__関数が呼び出されます。私がこれを確認したのは、print文を__init__ funcitonsに入れて、両方を出力したことです。 –

+0

私は、最初の子と2番目の子の間の祖父母を呼び出すので、順序は深さ優先ではないと思います。各スーパーコールは1つの新しいメソッドを呼び出すだけですが、呼び出された各メソッドもスーパーを呼び出すとチェーンされます。 –

+0

私は走査順序を明確にしました。順序はL→Rで、最初は深さ(2番目の親を試す前に祖父母を試す)ですが、それは、祖父母の前に親を試す(先行走査)。 – Niobos

関連する問題