Pythonのクラス継承:既存のクラスを元に新しいクラスを作る

クラスの最後のテーマは「継承」です。継承を使うことで、既存のクラスの機能を引き継ぎながら、新しい機能を追加したクラスを効率よく作ることができます。

継承とは

継承は、既存のクラスを元にして新しいクラスを作ることです。

  • 親クラス(スーパークラス): 元となるクラス
  • 子クラス(サブクラス): 親クラスを継承して作られた新しいクラス

子クラスは、親クラスのメソッドやインスタンス変数をそのまま使えます。さらに、子クラス独自のメソッドを追加することも可能です。

継承の基本構文

構文: class 新しいクラス名(元となるクラス名):

# 親クラス
class Animal:
    def __init__(self, name):
        self.name = name
    
    def speak(self):
        print(f"{self.name}が鳴いています")

# 子クラス(Animalを継承)
class Dog(Animal):
    def fetch(self):
        print(f"{self.name}がボールを取ってきました")

# 子クラスのインスタンスを生成
my_dog = Dog("ポチ")
my_dog.speak()   # ポチが鳴いています(親クラスのメソッドが使える)
my_dog.fetch()   # ポチがボールを取ってきました(子クラス独自のメソッド)

子クラスは親クラスのメソッドをそのまま使えるため、同じコードを書き直す必要がありません。

継承のメリット

# 継承なしの場合(コードが重複する)
class Dog:
    def __init__(self, name):
        self.name = name
    
    def speak(self):
        print(f"{self.name}が鳴いています")
    
    def fetch(self):
        print(f"{self.name}がボールを取ってきました")

class Cat:
    def __init__(self, name):  # Dogと全く同じ
        self.name = name
    
    def speak(self):            # Dogと全く同じ
        print(f"{self.name}が鳴いています")
    
    def purr(self):
        print(f"{self.name}がゴロゴロ言っています")
# 継承ありの場合(コードがスッキリ)
class Animal:
    def __init__(self, name):
        self.name = name
    
    def speak(self):
        print(f"{self.name}が鳴いています")

class Dog(Animal):
    def fetch(self):
        print(f"{self.name}がボールを取ってきました")

class Cat(Animal):
    def purr(self):
        print(f"{self.name}がゴロゴロ言っています")

共通の処理は親クラスにまとめることで、コードの重複を防げます。

オーバーライド:親クラスのメソッドを上書きする

オーバーライドとは、親クラスにあるメソッドと同じ名前のメソッドを子クラスで定義することで上書きすることです。

class Animal:
    def speak(self):
        print("動物が鳴いています")

class Dog(Animal):
    def speak(self):  # 親クラスのspeakをオーバーライド
        print("ワンワン!")

class Cat(Animal):
    def speak(self):  # 親クラスのspeakをオーバーライド
        print("ニャーニャー!")

dog = Dog("ポチ")
cat = Cat("タマ")

dog.speak()  # ワンワン!(子クラスのspeakが実行される)
cat.speak()  # ニャーニャー!(子クラスのspeakが実行される)

子クラスで同名のメソッドを定義すると、親クラスのメソッドが上書きされます。

super():親クラスのメソッドを呼び出す

オーバーライドした場合でも、親クラスのメソッドを利用したいことがあります。そのときに使うのが super() です。

構文: super().メソッド名()

class Animal:
    def speak(self):
        print("動物が鳴いています")

class Dog(Animal):
    def speak(self):
        super().speak()          # 親クラスのspeakを実行
        print("(犬の場合)ワンワン!")  # 子クラス独自の処理を追加

dog = Dog()
dog.speak()
# 動物が鳴いています
# (犬の場合)ワンワン!

疑問:super().メソッド名()でselfが不要な理由

今回の学習で気になったのが、super().メソッド名() を使う際に self が不要な点です。

通常のメソッド定義では第1引数に self が必要でした。しかし super().speak() のように呼び出す側では self を書きません。

理由: super() 自体が、すでに「現在のインスタンス(self)」の情報を持っているからです。

class Dog(Animal):
    def speak(self):
        # super()は内部的にselfを知っている
        # そのため、呼び出す側でselfを渡す必要がない
        super().speak()  # selfは不要

メソッドを定義するときは self が必要(誰が呼んだか分からないため)ですが、super() を通じて呼び出すときは super() がすでにインスタンスを把握しているため self は不要です。

今日の学びのポイント

  • 継承: class 子クラス名(親クラス名): で定義
  • 子クラスは親クラスのメソッドをそのまま使える
  • 子クラスに独自のメソッドを追加することも可能
  • オーバーライド: 同じ名前のメソッドを子クラスで定義して上書き
  • super(): 親クラスのメソッドを呼び出す
  • super().メソッド名()self が不要なのは、super() がすでにインスタンス情報を持っているため

継承はPythonのオブジェクト指向プログラミングの核心的な概念です。コードの再利用性を高め、保守しやすいプログラムを作るために欠かせない技術です。


コメント