多重継承とは、クラスが複数の親クラスから同時に継承することができる能力であり、Pythonにおいては他のOOP言語(例えばC++)の影響で登場しました。これにより再利用可能なミキシンを作成するための助けとなります。メソッド検索のメカニズム(MRO)の開発には時間がかかり、メソッドの衝突を確実に予測可能にすることが重要です。
クラスは異なる基底クラスから同じ名前のメソッドを取得することがあります。どのメソッドを呼び出すべきかをどう判断するのか?明確なスキームがないと、難解なエラーを引き起こします。
PythonはMRO(C3リニアリング)アルゴリズムを実装しており、階層内の衝突を解決する際にメソッドを検索する厳密な順序を定義します。super()関数やクラスの__mro__メソッドを使用することで、継承のチェーンを分析することで全てが明確になります。
コードの例:
class A: def foo(self): print("A") class B(A): def foo(self): print("B") super().foo() class C(A): def foo(self): print("C") super().foo() class D(B, C): def foo(self): print("D") super().foo() D().foo() print(D.__mro__)
主な特徴:
__mro__を通じて確認できます;親メソッドの名前が一致した場合、どうなるか?
回答: メソッドの呼び出しは、MROで定義された順序に従います。要求された名前のメソッドがチェーン内で最初に見つかったものが機能します。
明示的にselfを渡さずにsuper()を使用できますか?
回答: Python 3では可能で、クラスメソッドの本文内でのsuper().method()は、明示的にsuper(クラス, self).method()と同等ですが、クラス内のみで機能します。
既存のクラスのMROの順序を変更できますか?
回答: クラスが宣言された後、MROの順序は静的ですが、調べることはできます(または異なる継承順序の新しいクラスを作成することができます)。
プロジェクトで似たようなメソッドを持つ2つのミキシンが作成され、継承したクラスは両方のミキシンを使用しますが、クラス名を介してメソッドを直接呼び出し、イベントの順序を破ります。
利点:
欠点:
各ミキシンのメソッドでsuper()を使用し、チェーンに沿った呼び出しを保証し、必要な動作のスキップを避けます。
利点:
欠点: