Select Language

AI Technology Community

7.10、Pythonクラスの派生(派生クラス)

派生はオブジェクト指向プログラミングの基本概念であり、ある基礎クラスに基づいて新しいクラスを簡単に作成する能力を私たちに与えます。派生クラスのメソッドを使用することで、他人のコードを再利用でき、ゼロから自分のコードを作成する必要がありません。

既存のクラスに基づいて新しいクラスを定義する方法は次のとおりです:

def 新しいクラス(既存のクラス):
    pass

既存のクラスは、時には基底クラス親クラスとも呼ばれます;新しいクラスは派生クラス子クラスとも呼ばれます。派生クラスは基底クラスのすべての属性を継承します。

次の例では、車両は基底クラスで、自動車と自転車は派生クラスであり、どちらも車両のすべてのメンバーを継承しています。

>>> class Vehicle:                    # 車両クラス
...     def __init__(self):
...         self.cycle_number = 0
...         self.price = 0
...         self.producer = ""
...     def get_price(self):
...         return self.price
...     def set_price(self, price):
...         self.price = price
...
>>> class Bicycle(Vehicle):           # 自転車クラス、車両クラスから派生
...     def __init__(self):
...         pass
...
>>> class Car(Vehicle):               # 自動車クラス、車両クラスから派生
...     def __init__(self):
...         pass
...
>>> car_a = Car()
>>> bicycle_a = Bicycle()
>>> car_a.set_price(100000)           # set_price()は基底クラスから継承されたもの
>>> car_a.get_price()                 # get_price()も基底クラスから継承されたもの
100000
>>> bicycle_a.set_price(200)
>>> bicycle_a.get_price()
200


派生クラスのコンストラクタでは、明示的に親クラスのコンストラクタを呼び出す必要があることに注意してください。明示的に呼び出さない場合、基底クラスのコンストラクタは実行されません。これはC++やJavaとは異なります。C++とJavaでは、派生クラスを作成する際に基底クラスのコンストラクタが自動的に呼び出されます。

>>> class Vehicle:                 # 車両クラス
...     def __init__(self):
...         print("Vehicleのコンストラクタが実行中")
...
>>> class Bicycle(Vehicle):
...     def __init__(self):
...         pass
...
>>> bicycle_a = Bicycle ()


上記からわかるように、基底クラスVehicleのコンストラクタは実行されていません。親クラスのコンストラクタを明示的に呼び出すには、super().__init__()を使用できます。

>>> class Vehicle:             # 車両クラス
...     def __init__(self):
...         print("Vehicleのコンストラクタが実行中")
...
>>> class Bicycle(Vehicle):
...     def __init__(self):
...         super().__init__()
...
>>> bicycle_a = Bicycle()
Vehicleのコンストラクタが実行中

多重継承

Pythonでは、1つのクラスが複数の既存クラスから派生することができます。この特性が多重継承です。Pythonのこの特性はC++に似ており、Javaなどの一部の言語では多重継承がサポートされていません。

多重継承の構文形式は次のとおりです:

class 新しいクラス(既存クラス1, 既存クラス2, ....):
    pass

次に3つのクラスを定義します:

  1. 1つ目のクラスはBirdsで、すべての鳥類を表します。鳥類は卵を産むので、lay_egg()というインターフェース関数を提供します;

  2. 2つ目のクラスはCanSwimで、泳げる水生生物を表します。魚やアザラシなどを表すことができ、swim()というインターフェース関数を提供して、泳いでいることを表します;

  3. 3つ目はペンギンクラスPenguinで、ペンギンは卵を産み、泳ぐことができるので、BirdsとCanSwimから継承させることができます。


このようにすると、Penguinクラスには自動的にswim()とlay_egg()という2つのインターフェース関数があり、具体的な実装はそれぞれCanSwimとBirdsで定義されています。

次は完全なコードです。

>>> class Birds:
...     """鳥類"""
...     def lay_egg(self):
...         print(u"卵を産んでいます")
...
>>> class CanSwim:
...     """水生生物"""
...     def swim(self):
...         print(u"泳いでいます")
...
>>> class Penguin(CanSwim, Birds):
...     """ ペンギン """
...     def __init__(self):
...         pass
...
>>> pg_obj1 = Penguin()
>>> pg_obj1.swim()
泳いでいます
>>> pg_obj1.lay_egg()
卵を産んでいます


多重継承では、ある関数が2つ以上の基底クラスで定義されている場合、どちらの関数を使用すべきでしょうか?先ほどの例を使って説明します。どんな生物でも誕生と死亡があり、ここでは鳥類と水生生物にdie()というインターフェース関数を追加して、どのdie()が実行されるかを見てみましょう。

>>> class Birds:
...     """鳥類"""
...     def lay_egg(self):
...         print(u"卵を産んでいます")
...     def die(self):
...         print(u"鳥類が死亡しました")
...
>>> class CanSwim:
...     """水生生物"""
...     def swim(self):
...         print(u"泳いでいます")
...     def die(self):
...         print(u"水生生物が死亡しました")
...
>>> class Penguin(CanSwim, Birds):   # ペンギンクラスを定義
...     """ ペンギン """                  # 2つの親クラスでdie()インターフェース関数が定義されています
...     def __init__(self):
...         pass
...
>>> rb_obj1 = Penguin()
>>> rb_obj1.swim()
泳いでいます
>>> rb_obj1.lay_egg()
卵を産んでいます
>>> rb_obj1.die()                 # 最後にCanSwimのdie()インターフェース関数が使用されました
水生生物が死亡しました


最初の基底クラスのインターフェース関数が継承されることがわかります。つまり、CanSwimクラスのdie()が継承されます。2つの基底クラスの順序を入れ替えると、継承されるdie()インターフェース関数はBirdsクラスのものになることがわかります。

>>> class Birds:
...     """鳥類"""
...     def lay_egg(self):
...         print(u"卵を産んでいます")
...     def die(self):
...         print(u"鳥類が死亡しました")
...
>>> class CanSwim:
...     """水生生物"""
...     def swim(self):
...         print(u"泳いでいます")
...     def die(self):
...         print(u"水生生物が死亡しました")
...                                                                            # クラス定義終了
>>> class Penguin(Birds, CanSwim):   # 基底クラスの順序を入れ替えました
...     """ ペンギン """
...     def __init__(self):
...         pass
...

post
  • 10

    item of content
前の章では、リストや辞書などのPythonの予め定義されたデータ型について説明しました。しかし、自分で新しいタイプを定義したい場合、クラスを使用する必要があります。つまり、クラスを使用することで自分だけのデータ型を定義でき、システムで定義された型だけを使う以上のことができます。
クラスはオブジェクト指向プログラミングにおいて非常に基本的な概念であり、最も基本的な機能は新しいデータ型を作成することです。さらに、クラスAから新しいクラスBを派生させることができ、その際クラスBはクラスAのすべての属性を継承します(これを継承機能と呼びます)。
この章では、クラスの定義と使用方法について説明します。具体的には、クラスのプロパティとメソッド、クラスの派生方法、多重継承の使用方法などを解説します。