🤔
結局どっち?Pythonの「継承」と「委譲」の違いを5分で理解する
はじめに
Python でクラス設計をする際、「継承を使うべきか?それとも委譲を使うべきか?」と悩むことはありませんか?
- 継承の方が簡単だから、とりあえず継承を使う
- でも、継承を使いすぎるとコードの修正が面倒になる…
- どんなときに委譲を使えばよいのか、よくわからない
こうした疑問を5分でスッキリと解決できるように、クラス継承と委譲の違い、メリット・デメリット、適切な使い分け方 をわかりやすく解説します!
🏁 TL;DR(要約)
-
継承(Inheritance):「○○は△△である(is-a)」の関係
- 例:
Dog
はAnimal
である - 親クラスの機能をそのまま使える & オーバーライドで変更可能
- 例:
-
委譲(Delegation):「○○は△△を持っている(has-a)」の関係
- 例:
Robot
はSpeaker
を持っている - クラスのインスタンスを持ち、一部の処理を「任せる」
- 例:
-
選び方のポイント
- 「共通の性質」を持たせたい → 継承が有効
- 「個別の機能」を分け、柔軟に変更したい → 委譲が便利
🧬 クラス継承(Inheritance)とは
「クラス継承」とは、既存のクラス(親クラス)の機能を、新しいクラス(子クラス)が引き継ぐ仕組みです。
子クラスは親クラスのメソッドやプロパティを引き継ぎ、そのまま使うことも、一部を変更(オーバーライド)することもできます。
🧬 クラス継承の例(Python)
from abc import ABC, abstractmethod
# 親クラス(スーパークラス)
class Animal(ABC): # Animal は抽象クラスにする
def __init__(self, name):
self.name = name
@abstractmethod
def speak(self):
pass # ここでは実装しない(サブクラスで実装しないとエラー)
# 子クラス(Animal を継承)
class Dog(Animal):
def speak(self):
return "ワンワン"
class Cat(Animal):
def speak(self):
return "ニャー"
dog = Dog("ポチ")
cat = Cat("タマ")
print(dog.name, ":", dog.speak()) # ポチ : ワンワン
print(cat.name, ":", cat.speak()) # タマ : ニャー
✅ 継承のメリット
✔ 親クラスの機能をそのまま使える(コードの重複を減らせる)
✔ サブクラスごとに動作を変更できる(オーバーライド可能)
❌ 継承のデメリット
× 親クラスに依存しすぎると変更に弱くなる(親クラスを変更すると、影響が大きい)
× 不要なメソッドまで継承してしまうことがある
🎁 委譲(Delegation)とは
「委譲」とは、あるクラスが他のクラスの機能を 「持つ」ことで機能を利用する 方式です。
クラス同士が直接つながらないため、柔軟に変更しやすい設計 が可能になります。
🎁 委譲の例(Python)
# 役割を分担するクラス
class Speaker:
def speak(self):
return "こんにちは!"
# Robot クラスが Speaker を「持つ」(委譲)
class Robot:
def __init__(self, name):
self.name = name
self.speaker = Speaker() # Speakerクラスのインスタンスを持つ
def introduce(self):
return f"私はロボットの {self.name} です。{self.speaker.speak()}"
robot = Robot("AI-001")
print(robot.introduce()) # 私はロボットの AI-001 です。こんにちは!
✅ 委譲のメリット
✔ クラスの独立性が高く、変更しやすい(Speaker
を別のクラスに差し替え可能)
✔ 機能を小さく分けられる → コードがシンプル&管理しやすい
❌ 委譲のデメリット
× コードの記述が増える(継承よりも少し面倒)
× 適切に設計しないと、やり取りが複雑になりがち
🔍 クラス継承 vs 委譲:使い分けのポイント
クラス継承(Inheritance) | 委譲(Delegation) | |
---|---|---|
関係性 | 「is-a 関係」 → Dog は Animal である | 「has-a 関係」 → Robot は Speaker を持っている |
方法 | 親クラスの機能をそのまま使う(上書き可) | 別クラスのインスタンスを持ち、機能を「委譲」する |
メリット | コードの再利用がしやすい | クラスの責務を分け、柔軟な設計が可能 |
デメリット | 結合度が高くなりすぎる可能性 | クラス間の依存が増えすぎると複雑化 |
適用例 | すべてのオブジェクトが共通の性質を持つとき | 機能ごとに明確な責任を持たせたいとき |
🚀 結局どっちを使うべき?
✅ クラス継承が向いているケース
-
共通の性質 を持つオブジェクトを作りたい
- 例: すべての動物が「話す」機能を持つ(
Animal
→Dog
/Cat
)
- 例: すべての動物が「話す」機能を持つ(
✅ 委譲が向いているケース
-
機能を分けて独立性を高めたい
- 例:
Robot
に「話す機能」を別クラス(Speaker
)として持たせる
- 例:
👉 迷ったら「委譲」を優先し、どうしても必要な場合のみ「継承」を使うと管理しやすい!
🎯 まとめ
- 「○○は△△である」なら → 継承
- 「○○は△△を持っている」なら → 委譲
- 適切な設計を選ぶことで、保守性の高いコードが書ける!
💡 あなたのクラス設計、適切に「継承」と「委譲」を使い分けられていますか? 💡
Discussion