【Python】クラスの拡張とオーバーライドの仕組み

【Python】クラスの拡張とオーバーライドの仕組み

クラスの継承とは

クラスの継承とは、既存のクラス(スーパークラス、親クラス)の機能を引き継ぎつつ、新たな機能を追加する仕組みです。

class Animal:
    def speak(self):
        print("何か音を出します")

class Dog(Animal):
    def speak(self):
        print("ワンワン!")

dog = Dog()
dog.speak()  # 出力: ワンワン!

メソッドのオーバーライド

メソッドのオーバーライドとは、親クラスのメソッドを子クラスで上書きすることです。

class Parent:
    def show_message(self):
        print("親クラスのメッセージ")

class Child(Parent):
    def show_message(self):
        print("子クラスのメッセージ")

obj = Child()
obj.show_message()  # 出力: 子クラスのメッセージ

super() を使ったスーパークラスの呼び出し

オーバーライドしたメソッド内で、親クラスのメソッドを呼び出したい場合は super() を使います。

class Parent:
    def greet(self):
        print("こんにちは、親クラスです")

class Child(Parent):
    def greet(self):
        super().greet()
        print("こんにちは、子クラスです")

obj = Child()
obj.greet()
# 出力:
# こんにちは、親クラスです
# こんにちは、子クラスです

コンストラクタのオーバーライド

コンストラクタ(__init__ メソッド)もオーバーライドできます。super() を使うと、親クラスの初期化処理を呼び出せます。

class Parent:
    def __init__(self, name):
        self.name = name
        print(f"親クラス: {self.name}")

class Child(Parent):
    def __init__(self, name, age):
        super().__init__(name)
        self.age = age
        print(f"子クラス: {self.age}歳")

obj = Child("太郎", 10)
# 出力:
# 親クラス: 太郎
# 子クラス: 10歳

多重継承とメソッド解決順序(MRO)

Pythonでは、複数の親クラスを持つ多重継承が可能です。MRO(メソッド解決順序)を理解しておくことが重要です。

class A:
    def show(self):
        print("Aのshow")

class B(A):
    def show(self):
        print("Bのshow")

class C(A):
    def show(self):
        print("Cのshow")

class D(B, C):
    pass

obj = D()
obj.show()  # 出力: Bのshow
print(D.mro())  # MROの確認

抽象メソッドとオーバーライド

抽象メソッドを定義すると、すべてのサブクラスでメソッドをオーバーライドすることが強制されます。

from abc import ABC, abstractmethod

class Animal(ABC):
    @abstractmethod
    def make_sound(self):
        pass

class Dog(Animal):
    def make_sound(self):
        print("ワンワン!")

dog = Dog()
dog.make_sound()  # 出力: ワンワン!

プロパティのオーバーライド

Pythonの@propertyデコレータを使うと、プロパティをオーバーライドできます。

class Parent:
    @property
    def value(self):
        return "親クラスの値"

class Child(Parent):
    @property
    def value(self):
        return "子クラスの値"

obj = Child()
print(obj.value)  # 出力: 子クラスの値

オーバーライドのベストプラクティス

  • オーバーライドする場合、super() を使って親クラスの動作を適切に呼び出す。
  • 不要なオーバーライドは避け、可能な限り親クラスの機能を活用する。
  • 抽象クラスを使って、明示的にオーバーライドを強制することも有効。
  • プロパティのオーバーライド時には@property を適切に使う。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です