クラスの継承
一般的に オブジェクト指向言語 においては、あるクラスをひな型として部分的に機能を改造したクラスを作ることを クラスの継承 (inheritance) とよびます。
ひな型となるクラスを スーパークラス (親クラス) とよび、スーパークラスをもとにつくられたクラスを サブクラス (子クラス) といいます。
以前の記事 で定義した Rectanglesクラスを再掲し、それをひな型として、サブクラスを設計してみます。
新しいメソッドの追加
サブクラスは class文
によって定義することができます。サブクラスは初期化メソッドも含めて、スーパークラスのすべてのメソッドをそのまま受け継ぎます。サブクラスのスイート(機能を記述する場所)に新しい名前のメソッドを定義すると、サブクラスから生成されたインスタンスは、スーパークラスのメソッドに加えて、新しいメソッドを使えるようになります。
# PYTHON_CLASS_INHERITANCE-1
# Rectanglesクラスの定義
class Rectangles:
def __init__(self, a, b):
self.width = a
self.length = b
def area(self):
return self.width * self.length
# Rectanglesクラスを継承してRectangles_2クラスを作成
class Rectangles_2(Rectangles):
# 新しいメソッドの追加
def perimeter(self):
return self.width * 2 + self.length * 2
# Rectangles_2クラスのインスタンスを生成
rec = Rectangles_2(5, 10)
# スーパークラスRectangleのメソッドを使用
print("面積", rec.area())
# サブクラスRectangle_2で追加されたメソッド
print("周長", rec.perimeter())
面積 50 周長 30
上のサンプルコードではサブクラスに perimeter() という、周の長さを返すメソッドが追加されています。Rectangles_2クラスから作られたインスタンスは、もとの Rectanglesクラスのメソッドを用いて面積を計算することもできるし、Rectangles_2クラスで追加された新しいメソッドを使って周長を求めることもできます。
メソッドのオーバーライド
サブクラスのスイートに、スーパークラスで定義されているものと同じ名前でメソッドを定義すると、そのメソッドは上書きされます。つまり、サブクラスから作られたインスタンスは、この上書きされたほうのメソッドを実装し、スーパークラスのメソッドは呼び出されません。これを メソッドのオーバーライド とよびます。以下のサンプルコードでは、Rectanglesクラスの area()メソッドを上書きして、「面積は~です」という文字列を返すように修正します。
# PYTHON_CLASS_INHERITANCE-2
# Rectanglesクラスを継承してRectangles_3クラスを作成
class Rectangles_3(Rectangles):
#スーパークラスのarea()メソッドを上書き
def area(self):
return "面積は" + str(self.width * self.length) + "です。"
# Rectangles_3クラスのインスタンスを生成
rec = Rectangles_3(5, 10)
# 上書きされたメソッドを使用
print(rec.area())
面積は50です。
super()関数によるスーパークラスの呼び出し
初期化メソッドについても、上述のような方法でオーバーライドすることができますが、スーパークラスの設計内容に変更があったときにサブクラスの動作に不具合が生じる可能性もあります。そこで一般的には、初期化メソッドに変更を加えるときには、super()関数 でスーパークラスを呼び出します。以下のサンプルコードでは、Rectanglesクラスをもとに Squares という正方形クラスを設計し、初期化メソッドを上書きしています。
# PYTHON_CLASS_INHERITANCE-3
# Rectanglesクラスを継承してSquaresクラスを作成
class Squares(Rectangles):
# super()関数でスーパークラスをよびだし、
# 初期化メソッドの引数a,bにxを渡す
def __init__(self, x):
super().__init__(x, x)
# Squaresクラスのインスタンスを作成
sq = Squares(10)
# 正方形の面積を計算
print(sq.area())
100
長方形は二辺の長さを指定する必要がありますが、正方形ならば一辺の長さを与えれば性質が定まります。したがって、Squaresクラスのインスタンスを作るときには、x という1つの引数だけを与えるように設計しますが、
def __init__(self, x): super().__init__(x, x)
という記述によって、x をスーパークラスの引数 a, b に渡しています。つまり、a = x, b = x という代入が行われ (a, b は等しい値をもちます)、これをスーパークラスのインスタンス変数(データ属性)の self.width と self.length に渡して、area()メソッドの計算に用いるという仕組みになっています。
下記は誤植と思われますので、ご確認ください。
「新しいメソッドの追加」の説明文で、
class サブクラス名( スーパークラス名 ) → class サブクラス名( スーパークラス名 ) :
おお! 本当ですね!
「:」ひとつ抜けても、コードは動かないので注意が必要ですね。
それにしても、よく気づかれましたね …
助かりました。m(_ _)m