<一覧に戻る

Pythonで学ぶオブジェクト指向のオーバーライド(Override)

「親クラスの機能はだいたいそのままで、ここだけ自分用に変えたい…」そんなときに使えるのが、オブジェクト指向のオーバーライド(Override)です。

Pythonのクラスと継承を使えば、既存の振る舞いを活かしながら必要な部分だけを上書きできます。 IT初心者の方でも安心して読み進められるよう、基本から丁寧に解説していきます。

オーバーライドとは?まずイメージから

オーバーライドとは、親クラスにあるメソッドと同じ名前のメソッドを子クラスで書き直すことです。 同じ「speak」という名前でも、犬なら犬らしく、猫なら猫らしく振る舞ってほしいですよね?その「同じ名前だけど中身は違う」を実現するのがオーバーライドです。

「同じメソッド名なのに結果が変わるってどういうこと?」と不思議に感じるかもしれませんが、これがオブジェクト指向の強みです。

コードの再利用と柔軟なカスタマイズを両立できます。

サンプルコード:Animal、Dog、Catで学ぶ

次のコードでは、共通の親クラス Animal と、子クラス Dog と Cat を用意します。 Dog と Cat は、同じ speak というメソッドをそれぞれのルールで上書きします。

class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        return "ワーワーと鳴きます。"

class Dog(Animal):
    def speak(self):
        return f"{self.name}はワンワンと鳴きます。"

class Cat(Animal):
    def speak(self):
        return f"{self.name}はニャーニャーと鳴きます。"

pochi = Dog("ポチ")
mike = Cat("ミケ")

print(pochi.speak())  # 出力: ポチはワンワンと鳴きます。
print(mike.speak())   # 出力: ミケはニャーニャーと鳴きます。

まず Animal クラスが基準になります。__init__ で名前を受け取り、インスタンスの属性として保存します。speak は「動物の一般的な鳴き方」を返すだけの、いわばデフォルトの実装です。

そのうえで、Dog クラスは Animal を継承しながら speak を「犬らしく」書き換えます。インスタンスに保存してある name を使って「ポチはワンワン」と返すようにしています。同様に、Cat クラスも speak を「猫らしく」上書きします。

結果として、同じ speak という呼び出しでも、どのクラスのインスタンスかによって返り値が変わります。

「同じ名前で違う動作」——これがオーバーライドの基本です

オーバーライドしないとどうなる?

オーバーライドしないとどうなるでしょうか? 試しに、Animal を継承するけれど speak を上書きしないクラスを作ってみましょう。

class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        return "ワーワーと鳴きます。"

class Bird(Animal):
    pass

tori = Bird("ハト")
print(tori.speak())  # 出力: ワーワーと鳴きます。

Bird は speak を定義していないので、親クラス Animal の実装がそのまま使われます。

つまり、オーバーライドは必要なときだけすればよく、何もしなければ親の振る舞いを引き継げる、というわけです。ここが継承とオーバーライドの便利なところです。

なぜ同じ名前で切り替わるの?

Pythonは「今、どのクラスのインスタンスが使われているか」を見て、最も近いところ(子クラス側)にあるメソッドを優先して呼び出します。

この仕組みによって、同じ speak() という呼び出しでも、Dog なら犬用、Cat なら猫用の処理が実行されます。難しい用語では「メソッド解決」や「動的ディスパッチ」と呼ばれますが、要するに「その子に合ったやり方を選んでくれる」イメージでOKです。

オーバーライドの書き方のコツと注意点

「名前を同じにするだけでいいの?」と思うかもしれません。 基本的にはその通りですが、実務でつまずきやすいポイントをやさしく押さえておきましょう。

  • 親と同じメソッド名で定義することが大前提です。スペルミス(例: speek など)があると、上書きではなく「別のメソッドを追加しただけ」になってしまい、意図した動きになりません。
  • 引数の形は、親と揃えておくのが安全です。Python は厳密な「シグネチャ一致」を強制しませんが、呼び出し側のコードが想定通りに動かなくなることがあります。
  • 親の処理を「完全に置き換える」のではなく「一部だけ足したい」ときは、親のメソッドを呼び出す手があります。これは super() を使いますが、使い方は次のセクション「super() 関数の使い方」で詳しく解説します。

実践してみよう!

次に別のクラスを使って実践してみましょう! たとえば新しい動物 Fox を作って、speak をキツネらしく書き換えてみます。

class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        return "ワーワーと鳴きます。"

class Fox(Animal):
    def speak(self):
        return f"{self.name}はコンコンと鳴きます。"

kon = Fox("コン吉")
print(kon.speak())  # 出力: コン吉はコンコンと鳴きます。

Dog や Cat のときと同じ要領で書けましたか?この「同じ型の手順で増やせる」というのが、オブジェクト指向とオーバーライドの強力さです。

まとめ:オーバーライドで「共通」と「違い」を両立する

今回学習した内容をまとめます。

  • 親クラスの基本的なふるまいは再利用しつつ、子クラスで必要な部分だけを上書きできる——それがオーバーライドです。
  • 同じメソッド名を保ったまま振る舞いだけを変えられるので、コードは読みやすく、拡張もしやすくなります。

「同じ名前で、違う動きをさせる」——この感覚が身につくと、クラス設計が一気に楽になります。 次は super() を使って、上書きと「親の呼び出し」を上手に組み合わせる方法を学びましょう。

出力結果: