継承と委譲の違い
継承と委譲は、オブジェクト指向プログラミングにおいてコードの再利用や責務分担を実現するための手法ですが、アプローチが異なります。
以下に、Pythonの具体例を交えてそれぞれの概念と違いを解説します。
継承 (Inheritance)
継承は、あるクラス(サブクラス)が別のクラス(スーパークラス)の属性やメソッドを引き継ぐ仕組みです。
これにより、共通の機能をまとめて定義でき、サブクラスは必要に応じてその振る舞いを拡張・変更(オーバーライド)できます。
Pythonでの継承の例
# スーパークラス
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return "音が出る"
# サブクラス(継承によってAnimalの機能を引き継ぐ)
class Dog(Animal):
def speak(self):
return "ワンワン"
class Cat(Animal):
def speak(self):
return "ニャー"
# 使用例
dog = Dog("ポチ")
cat = Cat("タマ")
print(f"{dog.name}は {dog.speak()} と鳴く。") # 出力: ポチは ワンワン と鳴く。
print(f"{cat.name}は {cat.speak()} と鳴く。") # 出力: タマは ニャー と鳴く。
この例では、Dog と Cat クラスが Animal クラスを継承しているため、name の管理や共通の処理は Animal に任せ、各サブクラスは独自の speak() を実装しています。
委譲 (Delegation)
委譲は、オブジェクトが自分自身で直接機能を実装するのではなく、その機能を別のオブジェクトに委ねるパターンです。
これにより、クラス間の結合度を低くし、柔軟な設計を実現します。
# 委譲先のクラス
class Engine:
def start(self):
return "エンジンが始動しました。"
# 委譲元のクラス
class Car:
def __init__(self):
# CarはEngineオブジェクトを内包している(コンポジション)
self.engine = Engine()
def start(self):
# 自身でstartの実装をせず、エンジンのstart()に処理を委譲
return self.engine.start()
# 使用例
car = Car()
print(car.start()) # 出力: エンジンが始動しました。
この例では、Car クラスが直接エンジンの起動処理を実装するのではなく、Engine オブジェクトに処理を任せています。
これにより、Car クラスはエンジンの詳細な実装に依存せず、柔軟に設計できます。
まとめ
- 継承は、サブクラスがスーパークラスの属性やメソッドを受け継ぎ、必要に応じて拡張または変更する方法です。
- 例: Dog や Cat は Animal を継承して、共通の機能を再利用しながら独自の speak() を実装。
- 委譲は、あるオブジェクトが特定の機能を別のオブジェクトに任せる設計パターンです。
- 例: Car は Engine に start() の処理を委譲し、自身はエンジンの詳細を知らなくても動作する。
両者ともにコードの再利用や設計の柔軟性を高める手法ですが、継承はクラス間の強い結合を生むのに対し、委譲はより緩い結合を実現できるため、用途や設計思想に応じて適切に選択することが重要です。