継承とは (きもち)
クラス同士の 概念上・意味上の共通部分 を別のクラスとして 抽出 し、コードを共通化するためのしくみ。
割引にせよ、固定値値引きにせよ、どちらもキャンペーンであることに変わりはない。具体的には、たとえば、どちらも「定価からキャンペーンを適用した金額を計算できる」。継承のしくみを使うと、この共通部分を
Campaign
というクラスとして抽出し、
RateDiscountCampaign
と
ValueDiscountCampaign
がいずれも
Campaign
の一種であることを表明できる。
継承とは (プログラム的な話)
あるクラス (親クラス) のメンバーやメソッドを引き継いだ別のクラス (子クラス) を作成すること。
Python では次のように書く。
class 親クラス名:
def メソッドA(self):
print("Aが呼ばれたよ")
def メソッドB(self):
print("Bが呼ばれたからAを呼ぶよ")
self.メソッドA()
class 子クラス名(親クラス名):
pass
オーバーライド
継承には、メソッドのオーバーライドという仕組みがある。
親クラスで定義されたメソッドを、子クラスで上書きして定義すること。
これを行うためには、子クラスで同じ名前の関数を定義すれば良い。 (
@override
をつけるとより丁寧)
from typing import override
class 子クラス名(親クラス名):
# オーバーライドして上書きする。
# @override をつけると (うっかり同じ名前なってしまったんじゃなくて)
# 意図的にやっていることを表現できる。
@override
def メソッドA(self):
print("オーバーライドされたAだよ")
c = 子クラス名()
c.メソッドA()
# オーバーライドされたAだよ
ポリモーフィズム
親クラスに定義されているメソッドBがメソッドAを呼び出しているとする。
子クラスでメソッドAをオーバーライドしたとしよう。そのうえでメソッドBを実行すると、その中でメソッドAは親クラスで定義されていたもともとの振る舞いではなくオーバーライドされたメソッドAの振る舞いをする。これにより、メソッドBを一切書き換えることなしに、メソッドBが起こす結果を間接的に変化させることができる。
異なるクラスのインスタンスが同じ名前のメソッドを定義しているとき、そのメソッドが別のコードから呼び出された際に実際のインスタンスに応じた異なる挙動をすること。
例えば、以下のコードは
派生クラス1
と
派生クラス2
で異なる振る舞いをする。
class 基底クラス名:
def メソッドA(self):
print("Aが呼ばれたよ")
def メソッドB(self):
print("Bが呼ばれたからAを呼ぶよ")
self.メソッドA()
class 派生クラス名1(基底クラス名):
@override
def メソッドA(self):
print("1でオーバーライドされたAだよ")
class 派生クラス名2(基底クラス名):
@override
def メソッドA(self):
print("別の2でオーバーライドされたAだよ")
c1 = 派生クラス名1()
c1.メソッドB()
# Bが呼ばれたからAを呼ぶよ
# 1でオーバーライドされたAだよ
c2 = 派生クラス名2()
c2.メソッドB()
# Bが呼ばれたからAを呼ぶよ
# 別の2でオーバーライドされたAだよ