Python - 継承

Pythonでの継承とは?

継承は、オブジェクト指向プログラミング(OOP)の基本概念の一つで、あるクラスが別のクラスのプロパティとメソッドを継承することができます。これにより、同じコードを再度書くことなく、既存のクラスに基づいて新しいクラスを作成することができ、コードの再利用性とモジュラー性が向上します。Pythonでは、継承は class キーワードの後に親クラスの名前を括弧内に入れて実装されます。

Python - Inheritance

親クラスの作成

まず、簡単な親クラス Animal を作成しましょう:

class Animal:
def __init__(self, name):
self.name = name

def speak(self):
raise NotImplementedError("サブクラスはこのメソッドを実装する必要があります")

この例では、Animal クラスを定義し、__init__ メソッドで name 属性を初期化し、speak メソッドで NotImplementedError を発生させています。このエラーは、サブクラスが speak メソッドの独自の実装を提供しない場合に発生します。

子クラスの作成

次に、Animal クラスを継承した子クラス Dog を作成しましょう:

class Dog(Animal):
def speak(self):
return f"{self.name} は ワウ!と吠えます"

Dog クラスは、Animal クラスのすべての属性とメソッドを継承しますが、独自の実装を提供する speak メソッドを持ちます。Dog クラスのインスタンスを作成し、その speak メソッドを呼び出すと、エラーを発生させるのではなく、"[犬の名前] は ワウ!と吠えます" と表示されます。

my_dog = Dog("ブディ")
print(my_dog.speak())  # 出力: ブディ は ワウ!と吠えます

継承の種類

Pythonには3種類の継承があります:単一継承、複数継承、多段継承、以及び階層的継承です。それぞれのタイプを詳しく説明します。

Python - 単一継承

単一継承は最も一般的な継承形式で、クラスが1つの親クラスから継承する場合です。上記の Dog クラスが Animal クラスを継承するのは、単一継承の例です。

Python - 複数継承

複数継承は、クラスが複数の親クラスから継承する場合です。しかし、Pythonはクラス定義の構文で直接複数継承をサポートしていません。代わりに、"ミックスイン"または"インターフェース"技術を使用して複数継承を実現します。

メソッド解決順序(MRO)

Pythonは、C3線形化アルゴリズムを使用して、メソッドを探す際に親クラスを検索する順序を決定します。MROは、各クラスがメソッド解決順序に最大1回だけ現れ、クラス定義における親クラスの順序を保持することを保証します。

Python - 多段継承

多段継承は、クラスがサブクラスから継承することで、クラスの階層構造を形成する場合です。以下はその例です:

class Mammal(Animal):
pass

class Cat(Mammal):
def speak(self):
return f"{self.name} は ニャー!と鳴きます"

この場合、Cat クラスは Mammal クラスを継承し、Mammal クラスは Animal クラスを継承します。これにより、多段継承の階層構造が形成されます。

Python - 階層的継承

階層的継承は、複数のサブクラスが1つのスーパークラスを継承することを含みます。例えば:

class Reptile(Animal):
pass

class Snake(Reptile):
def speak(self):
return f"{self.name} は ヒス!と鳴きます"

class Lizard(Reptile):
def speak(self):
return f"{self.name} は クロールします"

この場合、SnakeLizard クラスはどちらも Reptile クラスを継承し、Reptile クラスは Animal クラスを継承します。これにより、階層的な継承構造が形成されます。

Python - 混合継承

混合継承は、複数継承と他の継承の特徴を組み合わせたものです。Pythonでは直接サポートされていませんが、ミックスインを使用するか、異なるタイプの継承を組み合わせることで実現できます。

super() 関数

super() 関数は、サブクラス内で親クラスのメソッドを呼び出すために使用されます。親クラスのメソッドを拡張またはオーバーライドしながら、その機能の一部を保持したい場合に特に役立ちます。以下はその例です:

class Bird(Animal):
def __init__(self, name, wingspan):
super().__init__(name)
self.wingspan = wingspan

def speak(self):
return f"{self.name} は チューブ!と鳴きます"

この場合、Bird クラスは Animal クラスを継承し、super() 関数を使用して親クラスの __init__ メソッドを呼び出します。これにより、name 属性が適切に初期化されます。また、Bird クラスは独自の実装を提供する speak メソッドを持ちます。

my_bird = Bird("チューティ", 10)
print(my_bird.speak())  # 出力: チューティ は チューブ!と鳴きます

継承を使用することで、より特殊化されたクラスを作成し、親クラスの機能を継承して拡張することができ、コードの再利用性と整理性が向上します。継承はOOPの一環に過ぎず、ポリモーフィズム、封印、抽象化といった他の概念も、堅牢で維持しやすいソフトウェアシステムを設計するために重要な役割を果たします。

Credits: Image by storyset