2020/11/01
Python【Python】クラスの継承とsuper()の使い方
Pythonでクラスを継承させる方法と、super()の使い方について説明します。
クラスについてのより基本的なことはこの記事に書いています。
はじめに、以下のコードをみてください。
SoccerPlayerクラスとBaseballPlayerクラス
class SoccerPlayer:
"""サッカー選手 クラス"""
def __init__(self, name, age):
self.name = name
self.age = age
def self_introduce(self):
print(f"私の名前は{self.name}、{self.age}才です。")
def kick(self):
print("キック!")
class BaseballPlayer:
"""野球選手 クラス"""
def __init__(self, name, age):
self.name = name
self.age = age
def self_introduce(self):
print(f"私の名前は{self.name}、{self.age}才です。")
def catch(self):
print("キャッチ")
SoccerPlayerクラスとBaseballPlayerクラスは、それぞれのクラスで固有のインスタンスメソッド(kickとcatch)を持っています。
一方で、self_introduceというメソッドは共通しています(全く同じコードになっている)し、保有する属性(nameとage)も共通しています。
プログラミングにおいては「同じことはなるべく繰り返し書かないようにする(DRY原則)」という考え方があります。同じコードを重複して書いている(__init__とself_introduceのコードを繰り返し書いている)上記のコードはもっと簡潔に書くことができます。
このときに使えるのが、「クラスの継承」です。 「name・age属性を持つこと」、「自己紹介メソッド(self_introduce)を持つこと」は、サッカー選手・野球選手に関わらずいわば「人」として共通している特徴なので人を表すPersonクラスを作ります。
そして、そのPersonクラスを継承したSoccerPlayerクラスとBaseballPlayerクラスを作るのです。
Personクラスを作って、処理を共通化
# Personクラスを作る → 共通のメソッド(__init__とself_introduce)はこのクラスに定義する
class Person:
"""人 クラス"""
def __init__(self, name, age):
self.name = name
self.age = age
def self_introduce(self):
print(f"私の名前は{self.name}、{self.age}才です。")
# クラス名の後ろに(Person)をつけて、Personクラスを継承したクラスにする
class SoccerPlayer(Person):
"""サッカー選手 クラス"""
def kick(self):
print("キック!")
# クラス名の後ろに(Person)をつけて、Personクラスを継承したクラスにする
class BaseballPlayer(Person):
"""野球選手 クラス"""
def catch(self):
print("キャッチ")
s1 = SoccerPlayer("本田", 20)
b1 = BaseballPlayer("長嶋", 30)
# SoccerPlayer・BaseBallPlayerクラスは、Personクラスを継承しているのでPersonクラスのメソッド(self_introduce)が使える
s1.self_introduce()
b1.self_introduce()
# 出力結果
私の名前は本田、20才です。
私の名前は長嶋、30才です。
メソッドの上書き(オーバーライド)
子クラスに、親クラスと同じ名前のメソッドを実装することで、親クラスのメソッドを上書きすることができます。
self_introduceメソッドを上書き
class Person:
"""人 クラス"""
def __init__(self, name, age):
self.name = name
self.age = age
def self_introduce(self):
print(f"私の名前は{self.name}、{self.age}才です。")
class SoccerPlayer(Person):
"""サッカー選手 クラス"""
# 親クラスと同じ名前のメソッドを定義する。
def self_introduce(self):
print(f"サッカー選手をやっている{self.name}と申します。")
def kick(self):
print("キック!")
s1 = SoccerPlayer("本田", 20)
# 子クラスのself_introduceが実行される
s1.self_introduce()
# 出力結果
サッカー選手をやっている本田と申します。
親クラスのメソッドを呼び出したいときは以下のようsuper()を使います。
親クラスのメソッドを実行
# super(<子クラス名>, <インスタンス>)で親クラスのメソッドを実行できる
super(SoccerPlayer, s1).self_introduce()
# 出力結果(Personクラスのself_introduceが実行される)
私の名前は本田、20才です。
クラス内でもsuper()
は使えます。クラス内で使う場合は、引数に子クラス名を書く必要はありません。
クラス内でsuper()を使う
class Person:
"""人 クラス"""
def __init__(self, name, age):
self.name = name
self.age = age
def self_introduce(self):
print(f"私の名前は{self.name}、{self.age}才です。")
class SoccerPlayer(Person):
"""サッカー選手 クラス"""
def self_introduce(self):
# 親クラスのメソッドを呼び出す
super().self_introduce()
print(f"サッカー選手をやっています。")
def kick(self):
print("キック!")
s1 = SoccerPlayer("本田", 20)
s1.self_introduce()
# 出力結果
私の名前は本田、20才です。
サッカー選手をやっています。
super()を__init__メソッド内で使う
super
は当然__init__メソッドでも使うことができます。
以下のように、SoccerPlayerクラスの__init__内で、Personの__init__を呼び出すことで、共通属性(name, age)の値の設定処理は共通化させることができます。
__init__関数内でsuper()を使う
class Person:
"""人 クラス"""
def __init__(self, name, age):
self.name = name
self.age = age
def self_introduce(self):
print(f"私の名前は{self.name}、{self.age}才です。")
class SoccerPlayer(Person):
"""サッカー選手 クラス"""
def __init__(self, name, age, is_daihyo):
# 親クラスの__init__を呼び出す。
super().__init__(name, age)
# is_daihyo属性はSoccerPlayerクラス固有の属性なのでここで値設定する
self.is_daihyo = is_daihyo
def self_introduce(self):
super().self_introduce()
print(f"サッカー選手をやっています。")
# 追加
if self.is_daihyo:
print("日本代表選手です。")
def kick(self):
print("キック!")
s1 = SoccerPlayer("本田", 20, True)
s1.self_introduce()
# 出力結果
私の名前は本田、20才です。
サッカー選手をやっています。
日本代表選手です。