Pythonのオブジェクト指向プログラミングを学ぶ上で、「継承」と並んで非常に重要な概念が「メソッドのオーバーライド」です。
親クラスが持つメソッド(機能)を子クラスが受け継ぎ、さらに子クラス独自の振る舞いを加えることができるこの仕組みは、柔軟で拡張性の高いコードを書くために不可欠なテクニックと言えるでしょう。
しかし、「メソッドのオーバーロードと何が違うの?」「super()
って何のために使うの?」といった疑問を持つ方も少なくありません。
そこでこの記事では、Pythonにおけるメソッドオーバーライドの基本から、親クラスのメソッドを拡張するsuper()
の使い方、そして実践的なメリットまで、具体的なサンプルコードを交えながら初心者にもわかりやすく徹底的に解説します。
【本記事の信頼性】
- 執筆者は元エンジニア
- 大手プログラミングスクールのWebディレクター兼ライターを経験
- 自らも地元密着型のプログラミングスクールを運営
受講生から評判の良いプログラミングスクール
スクール |
特徴 |
受講料金 |
大手比較サイトで4年連続人気NO.1!受講生からの評判も非常に高く、Web系のエンジニアを目指すならRUNTEQ一択。 | 550,000円(給付金適用あり) | |
月単価80万円以上の現役エンジニア講師による指導!一度入会すればサポートは半永久的。 | 498,000円 | |
格安で質の高いWeb制作スキルを習得したい人におすすめ!業界最安級の料金でありながら、コミュニティやサポートが充実。 | 129,800円~ | |
完全無料でプログラミングが学べる貴重なスクール!最短1ヶ月で卒業可能。ゼロスク運営会社への就職もできる。 | 無料 | |
長期間に渡って学習し、希少人材を目指す人に最適なスクール!受講料は高いものの、高収入を得られる人材を目指せる。 | 96~132万円 |
メソッドオーバーライドとは何か
オーバーライド(Override)とは、親クラス(スーパークラス)で定義されているメソッドを、子クラス(サブクラス)で改めて定義し直すこと、つまりメソッドの「上書き」を指します。
これにより、子クラスは親クラスの基本的な機能は継承しつつ、特定のメソッドの振る舞いだけを自身の特性に合わせて変更することが可能になります。
メソッドのオーバーライドは、クラスの「継承」が前提となる機能です。
早速、簡単な例を見てみましょう。
ここに、動物(Animal
)クラスと、それを継承した犬(Dog
)クラスがあります。
# 親クラス
class Animal:
def speak(self):
print("何らかの鳴き声")
# Animalクラスを継承した子クラス
class Dog(Animal):
# 親クラスのspeak()メソッドをオーバーライド
def speak(self):
print("ワン!")
# インスタンスを作成してメソッドを呼び出す
animal = Animal()
animal.speak()
dog = Dog()
dog.speak()
以下が実行結果です。
何らかの鳴き声
ワン!
Animal
クラスには、speak
というメソッドが定義されています。
Dog
クラスはAnimal
クラスを継承しているため、本来であればspeak
メソッドもそのまま受け継ぎます。
しかし、Dog
クラスの中で、もう一度同じspeak
という名前のメソッドを定義しました。
これがメソッドのオーバーライドです。
この結果、Dog
クラスのインスタンスであるdog
からspeak
メソッドを呼び出すと、親クラスのメソッドの処理は実行されず、Dog
クラスで再定義された「ワン!」という処理が実行されます。
このように、子クラスで定義されたメソッドが親クラスの同名メソッドよりも優先されるのが、オーバーライドの基本となります。
super()を使った親クラスのメソッド呼び出し
オーバーライドは、親クラスのメソッドを完全に上書きするだけではありません。
時には、「親クラスの元々のメソッド処理も実行しつつ、子クラスで追加の処理を行いたい」というケースがあります。
そのような場面で活躍するのが、組み込み関数のsuper()
です。
super()
を使うと、子クラスのメソッド内から、オーバーライド元の親クラスのメソッドを呼び出すことができます。
次の例では、猫(Cat
)クラスが、親のAnimal
クラスのspeak
メソッドを呼び出し、その上で独自の処理を追加しています。
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
print(f"{self.name}は鳴いた。")
class Cat(Animal):
def speak(self):
# super()を使って親クラスのspeak()メソッドを呼び出す
super().speak()
# 子クラス独自の処理を追加
print("ニャー")
cat = Cat("タマ")
cat.speak()
以下が実行結果です。
タマは鳴いた。
ニャー
Cat
クラスのspeak
メソッド内で、super().speak()
という記述があります。
これが「親クラスのspeak
メソッドを呼び出す」という命令です。
これにより、まず親クラスのspeak
メソッドが実行され、その直後に子クラスで定義された追加の処理が実行されます。
このようにsuper()
を活用することで、親クラスのメソッドを完全に上書きするのではなく、機能を拡張する形でオーバーライドを実装できるのです。
これは特に、__init__
メソッド(コンストラクタ)をオーバーライドする際によく使われるテクニックです。
メソッドオーバーライドのメリットと実践的な使いどころ
メソッドオーバーライドを理解すると、コードの柔軟性が格段に向上します。
その最大のメリットは、「ポリモーフィズム(Polymorphism / 多態性)」を実現できる点にあります。
ポリモーフィズムとは、異なるクラスのオブジェクトが、同じ名前のメソッド呼び出しに対して、それぞれ独自の振る舞いをする性質のことです。
言葉では少し難しいかもしれませんが、以下のコードを見ると一目瞭然でしょう。
class Animal:
def speak(self):
print("何らかの鳴き声")
class Dog(Animal):
def speak(self):
print("ワン!")
class Cat(Animal):
def speak(self):
print("ニャー")
class Cow(Animal):
def speak(self):
print("モー")
# Dog, Cat, CowはすべてAnimalの一種
animals = [Dog(), Cat(), Cow()]
# ループでそれぞれのオブジェクトのspeak()メソッドを呼び出す
for animal in animals:
animal.speak() # 同じメソッド呼び出しなのに、結果が異なる
以下が実行結果です。
ワン!
ニャー
モー
animals
リストには、Dog
やCat
といった異なるクラスのインスタンスが入っています。
しかし、これらはすべてAnimal
クラスを継承しているため、「動物」という共通の型として扱うことができます。
ループの中では、各オブジェクトの具体的なクラスを意識することなく、ただanimal.speak()
という同じ形式でメソッドを呼び出しているだけです。
それにもかかわらず、各インスタンスはオーバーライドされた自身のspeak
メソッドを正しく実行し、異なる結果を出力しました。
これがポリモーフィズムです。
この性質により、新しい動物クラスを追加してもループ部分のコードを一切変更する必要がなく、非常に拡張性の高いプログラムが実現できます。
メソッドオーバーロードとの違い
オーバーライドとよく混同される言葉に「オーバーロード(Overload)」があります。
この二つは全く異なる概念なので、違いを明確に理解しておきましょう。
メソッドオーバーライド | 親クラスのメソッドを、子クラスで再定義すること。 |
メソッドオーバーロード | 同じクラス内で、同じ名前のメソッドを、引数の数や型を変えて複数定義すること。 |
JavaやC++といった言語ではメソッドオーバーロードがサポートされていますが、Pythonは言語仕様としてメソッドオーバーロードをサポートしていません。
Pythonでは、同じクラス内で同じ名前のメソッドを複数定義した場合、単純に後から定義されたものが有効になり、前のものは上書きされてしまいます。
Pythonでは、引数のデフォルト値や可変長引数(*args
, **kwargs
)を使うことで、オーバーロードと似たような柔軟な引数の受け渡しを実現することが一般的です。
まとめ
今回は、Pythonのオブジェクト指向におけるメソッドのオーバーライドについて、その基本からsuper()
の使い方、オーバーロードとの違いなどについて解説しました。
なお、Pythonを体系的に学んだり、Pythonのスキルを高めたりするためには、プログラミングスクールを利用するのも有効です。
細かな疑問がすぐに解決するだけでなく、現役エンジニアが「質の高いポートフォリオ」を作成するための手助けをしてくれたり、エンジニア就職・転職のコツを教えてくれたりするなど、様々なメリットがありますので、独学に疲れた方は検討してみてはいかがでしょうか。