8-2
必要なデータは引数で渡す
他クラスの計算を使い回したいとき、継承して super() 経由で呼ぶと、親クラスの内部実装という「暗黙の経路」に依存してしまう。親がメソッドの呼び合い方を変えただけでサブクラスの計算が狂う。必要な計算オブジェクトはコンストラクタや引数で明示的に渡し、委譲(コンポジション)で使う。
出張旅費の深夜割増計算
✕ Bad
class TravelFare:
def one_way(self, km: int) -> int:
return km * 20
def round_trip(self, km: int) -> int:
return km * 38 # 往復は割安レート
class LateNightTravelFare(TravelFare):
def one_way(self, km: int) -> int:
return super().one_way(km) + 200 # 深夜割増
def round_trip(self, km: int) -> int:
return super().round_trip(km) + 400✓ Good
class LateNightTravelFare:
def __init__(self, base: TravelFare) -> None:
self._base = base # 必要な計算機は引数で明示的に受け取る
def one_way(self, km: int) -> int:
return self._base.one_way(km) + 200
def round_trip(self, km: int) -> int:
return self._base.round_trip(km) + 400Bad 版は、親が round_trip() の内部を「one_way() を2回呼ぶ」実装に変えた瞬間、オーバーライドした one_way() の割増が二重加算される。委譲なら親の内部がどう変わっても、受け取った結果に割増を足すだけなので壊れない。