継承
オブジェクト指向プログラミングをサポートする言語では、大抵継承と呼ばれる機能が実装されています。あるクラスを定義する際に親となるクラスを指定すると、そのクラスの機能をまるごと引き継ぐことが可能となりますが、この機能のことを継承と呼びます。
クラス定義と継承
Pythonで既存クラスを継承したクラスを定義する場合は、class文の後方に丸括弧で親クラスを指定します。なお、これまでのように親クラスを指定しない場合、objectクラスを継承したクラスとなります。
サンプルを見てみましょう。Base、Subという2つのクラスを定義しますが、SubはBaseクラスを継承するものとします。
class Base:
""" 親クラス """
def func1(self):
print('func1')
class Sub(Base):
""" 子クラス """
def func2(self):
print('func2')
obj = Sub() # 子クラスをインスタンス化
obj.func1()
obj.func2() # 親クラスのメソッドも実行可能
上のサンプルでは、継承によりSubクラスのfunc2に加え、親クラスのfunc1も呼び出すことができていることを確認することができます。
親クラスのメソッドの呼び出し
親クラスのメソッドを呼び出す際は、super()を使用します。
class Base:
def func1(self):
print('func1')
class Sub(Base):
def func2(self):
super().func1() # 親クラスのメソッドを呼び出し
print('func2')
obj = Sub()
obj.func2()
__init__とsuper
super()を使用すると初期化子__init__を使用してインスタンスの属性を設定することができます。以下のサンプルは、ユーザを表すUserクラスに対し、それを継承した社員を表すEmployeeクラスを定義しています。Userは属性としてname、ageを持ち、Employeeは属性として部署departmentを持つものとします。
class User:
"""
ユーザークラス
"""
def __init__(self, name="", age=0):
self.name = name
self.age = age
def say_name(self):
print("私の名前は" + self.name + "です。")
class Employee(User):
"""
社員クラス
"""
def __init__(self, name, age, department):
super().__init__(name, age)
self.department = department
def say_department(self):
print("私の部署は" + self.department + "です。")
e = Employee("Suzuki", 45, "営業部")
e.say_name() # 私の名前はSuzukiです。
e.say_department() # 私の部署は営業部です。
上のサンプルでサブクラスの方に__init__でインスタンス変数departmentが追加されています。
オーバーライド
また、派生クラスで親クラスのメソッドをオーバーライドすることもできます。先程のEmployeeのsay_nameメソッドをカスタマイズしてみます。
class Employee(User):
"""
社員クラス
"""
def __init__(self, name, age, department):
super().__init__(name, age)
self.department = department
def say_name(self):
print("名前は" + self.name + "、所属部署は" + self.department + "です。")
e = Employee("Suzuki", 45, "営業部")
e.say_name() # 名前はSuzuki、所属部署は営業部です。
このサンプルのように親クラスのメソッドを上書きする操作のことをオーバーライドと呼びます。
多重継承継承
Pythonでは複数のクラスを継承することができ、これを多重継承と呼びます。多重継承をする場合は、親クラスをカンマ区切りで指定します。
class Base1:
def func1(self):
print('func1')
class Base2:
def func2(self):
print('func2')
class Sub(Base1, Base2):
def func(self):
super().func1()
super().func2()
obj = Sub()
obj.func()
言語によってはアンチパターンとして扱われることもある多重継承ですが、再利用として非常に有用な手段でもあるためPythonの様々なライブラリで活用されています。Java等の単一継承言語育ちの方はMixinについて知っておくと利用や設計する際に一役買うかと思います。
