🤔

結局どっち?Pythonの「継承」と「委譲」の違いを5分で理解する

2025/02/08に公開

はじめに

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