【Python】レッスン5-06:メソッドのオーバーライドを理解しよう
一つ前のLessonではプロパティについて学習しました。
今回はメソッドのオーバーライドについて見ていきましょう。
Lesson1:基礎文法編
Lesson2:制御構造編
Lesson3:関数とスコープ編
Lesson4:データ構造編
Lesson5:オブジェクト指向編
・Lesson5-1:クラスの基本を理解しよう
・Lesson5-2:メソッドの基本を理解しよう
・Lesson5-3:カプセル化を理解しよう
・Lesson5-4:プロパティを理解しよう
・Lesson5-5:クラスの継承を理解しよう
・Lesson5-6:メソッドのオーバーライドを理解しよう ◁今回はココ
・Lesson5-7:静的メソッドを理解しよう
・Lesson5-8:モジュールを使いこなそう
・Lesson5-9:抽象クラスを理解しよう
・Lesson5-10:ミックスインを理解しよう
・Lesson5-11:データクラスを理解しよう
・練習問題5-1:モンスター捕獲ゲームを作ろう
・練習問題5-2:モンスターとのバトルゲームを作ろう
次のステップ:Python基礎習得者にお勧めの道5選(実務or副業)
オーバーライドとは? 継承関係におけるメソッドの再定義
ここからメソッドのオーバーライドの説明に入ります。
ページ下部にはこのページで出てくる用語の意味をまとめた 用語集 もありますので、分からない言葉が出てきたらそちらも参考にしてください。
メソッドのオーバーライドとは、親クラスで定義されたメソッドを子クラスで再定義する機能です。
オブジェクト指向プログラミングの重要な概念であり、親クラスのメソッドの基本的な動作を変更したい場合に使用されます。これにより、さらに柔軟なクラス設計が可能となります。
たとえば動物クラスに「鳴く」メソッドが定義されている場合、その動作を異なる動物ごとにカスタマイズすることができます。
メソッドのオーバーライドの使用例
ここでは動物のクラスを例にして、メソッドのオーバーライドを見ていきます。
親クラスで「鳴く」メソッドが定義されており、これを子クラスで上書き(オーバーライド)しています。
class Animal: # Animalクラスを定義 def sound(self): # soundメソッドを定義 print("動物が鳴いています") # メソッドのオーバーライドの例 class Dog(Animal): # Animalクラスを継承したDogクラスを定義 def sound_dog(self): # sound_dogメソッドを定義 print("ワンワン!") class Cat(Animal): # Animalクラスを継承したCatクラスを定義 def sound(self): # オーバーライド(親クラス内のメソッドと同名のメソッドを定義) print("ニャーニャー") dog = Dog() # インスタンス生成 dog.sound() # 親クラスのメソッドを呼び出し dog.sound_dog() # 子クラスのメソッドを呼び出し cat = Cat() # インスタンス生成 cat.sound() # soundメソッドは子クラス側でオーバーライド(上書き)されている # 出力: ニャーニャー
この例ではAnimal
という親クラスにmake_sound
というメソッドがあり、Dog
とCat
という子クラスでそれぞれ異なる実装を行っています。
Dog
クラスでは「ワンワン!」、Cat
クラスでは「ニャーニャー」と鳴く動作にオーバーライドされています。
このコードを実行すると、以下のように出力されます。
動物が鳴いています ワンワン! ニャーニャー
メソッドのオーバーライドの利点
メソッドのオーバーライドを使うことでコードの再利用性が向上し、柔軟に動作を変更することができます。
親クラスに共通のメソッドを定義し、子クラスで必要な場合にその動作をカスタマイズすることで、無駄なコードの繰り返しを防ぎ、保守性の高いコードを書くことが可能です。
またオーバーライドによって、子クラスに特有の振る舞いを簡単に実装できるため、クラス設計がより直感的になります。
まとめ
メソッドのオーバーライドは親クラスの機能を子クラスでカスタマイズするための強力な手段です。
この機能を使うことでコードの再利用性が高まり、オブジェクト指向プログラミングの利点を活かすことができます。
- サイト改善アンケート|ご意見をお聞かせください(1分で終わります)
-
本サイトでは、みなさまの学習をよりサポートできるサービスを目指しております。
そのため、みなさまの「プログラミングを学習する理由」などをアンケート形式でお伺いしています。1分だけ、ご協力いただけますと幸いです。
【Python】サイト改善アンケート
練習問題:オーバーライドを使ってみよう
この記事で学習した「オーバーライド」を復習する練習問題に挑戦しましょう。
問題|家電製品の動作をシミュレーションしよう
クラスの継承とメソッドのオーバーライドを使った家電製品のシミュレーションプログラムを作成しましょう。
親クラスで基本的な家電の操作を定義し、洗濯機と冷蔵庫の子クラスでそれぞれの動作をカスタマイズします。
以下の要件に従ってコードを完成させてください。
- 親クラス
Appliance
を定義し、名前を設定する__init__
メソッドを作成すること。 - 親クラスで家電製品を操作する
operate
メソッドを定義すること。 WashingMachine
クラスとRefrigerator
クラスを親クラスから継承し、それぞれのoperate
メソッドをオーバーライドすること。- 各家電の操作を順に出力すること。
ただし、以下のような実行結果となるコードを書くこと。
洗濯機で洗濯を開始します 冷蔵庫で冷蔵を開始します
ヒント|難しいと感じる人だけ見よう
1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。
- ヒント1【コードの構成を見る】
-
正解のコードは上から順に以下のような構成となっています。
1:家電製品の共通機能を持つ親クラス
Appliance
の定義
2:洗濯機専用の動作を持つ子クラスWashingMachine
の定義
3:冷蔵庫専用の動作を持つ子クラスRefrigerator
の定義
4:複数の家電をまとめて操作結果を表示する処理
- ヒント2【穴埋め問題にする】
-
以下のコードをコピーし、コメントに従ってコードを完成させて下さい。
# 親クラスの定義 class Appliance: """【穴埋め問題1】ここにApplianceクラスの初期化メソッド__init__を定義し、家電製品の名前を設定するコードを書いてください。""" """【穴埋め問題2】ここにoperateメソッドを定義し、家電製品の操作メッセージを返すコードを書いてください。""" # 子クラスの定義(洗濯機) class WashingMachine(Appliance): """【穴埋め問題3】ここにWashingMachineクラスのoperateメソッドをオーバーライドし、洗濯を開始するメッセージを返すコードを書いてください。""" # 子クラスの定義(冷蔵庫) class Refrigerator(Appliance): """【穴埋め問題4】ここにRefrigeratorクラスのoperateメソッドをオーバーライドし、冷蔵を開始するメッセージを返すコードを書いてください。""" # 家電製品のリストを作成し、それぞれの操作を出力します appliances = [WashingMachine("洗濯機"), Refrigerator("冷蔵庫")] # 各家電製品の操作を順に出力 for appliance in appliances: """【穴埋め問題5】ここに家電製品の操作メッセージを出力するコードを書いてください。"""
このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。
解答例|
例えば以下のようなプログラムが考えられます。
- 正解コード
-
# 親クラスの定義 class Appliance: # 初期化メソッド (__init__)、家電製品の名前を設定します def __init__(self, name): self.name = name # 親クラスのメソッド、家電製品の操作を定義します def operate(self): return f"{self.name}を操作しています" # 子クラスの定義(洗濯機) class WashingMachine(Appliance): # 親クラスのoperateメソッドをオーバーライドしています def operate(self): return f"{self.name}で洗濯を開始します" # 子クラスの定義(冷蔵庫) class Refrigerator(Appliance): # 親クラスのoperateメソッドをオーバーライドしています def operate(self): return f"{self.name}で冷蔵を開始します" # 家電製品のリストを作成し、それぞれの操作を出力します appliances = [WashingMachine("洗濯機"), Refrigerator("冷蔵庫")] # 各家電製品の操作を順に出力 for appliance in appliances: print(appliance.operate()) # 出力:洗濯機で洗濯を開始します, 冷蔵庫で冷蔵を開始します
解答例の解説|
正解コードをブロックごとに解説します。
- 詳細解説
-
家電製品の共通機能を持つ親クラス
Appliance
の定義# 親クラスの定義 class Appliance: # 初期化メソッド (__init__)、家電製品の名前を設定します def __init__(self, name): self.name = name # 親クラスのメソッド、家電製品の操作を定義します def operate(self): return f"{self.name}を操作しています"
このコードでは、家電製品の基本的な情報と動作をまとめた「親クラス」を作っています。
class Appliance:
これはクラスの定義で、「Appliance(家電)」という名前の設計図を作る宣言です。def __init__(self, name):
これは「初期化メソッド」と呼ばれ、インスタンス(オブジェクト)が作られたときに最初に呼び出されます。
引数name
で製品名を受け取り、それをself.name
という変数に保存します。self
は「そのオブジェクト自身」を表します。def operate(self):
これは家電を操作する動作を表すメソッドです。
実行すると、設定された製品名を使って○○を操作しています
という文章を返します。
この親クラスは、後で作る「洗濯機」や「冷蔵庫」などのクラスに共通する部分の土台となります。
洗濯機専用の動作を持つ子クラス
WashingMachine
の定義# 子クラスの定義(洗濯機) class WashingMachine(Appliance): # 親クラスのoperateメソッドをオーバーライドしています def operate(self): return f"{self.name}で洗濯を開始します"
このコードでは、「洗濯機」という家電を表すクラスを作っています。
class WashingMachine(Appliance):
クラス名の後ろの(Appliance)
は、「Applianceクラスを継承する」という意味です。
つまり、Appliance
クラスで作った機能(__init__
や変数)をそのまま引き継いで使えます。def operate(self):
親クラスにも同じ名前のoperate
メソッドがありますが、ここでは**「オーバーライド(上書き)」**しています。
これにより、洗濯機クラスでは「○○を操作しています」ではなく「○○で洗濯を開始します」というメッセージが返るようになります。- このようにオーバーライドを使うと、同じ「操作」という動作でも、家電の種類に応じた専用の挙動を実装できます。
冷蔵庫専用の動作を持つ子クラス
Refrigerator
の定義# 子クラスの定義(冷蔵庫) class Refrigerator(Appliance): # 親クラスのoperateメソッドをオーバーライドしています def operate(self): return f"{self.name}で冷蔵を開始します"
このコードでは、「冷蔵庫」という家電を表すクラスを作っています。
class Refrigerator(Appliance):
これは「Refrigerator(冷蔵庫)」クラスを作る宣言で、(Appliance)
によって親クラスAppliance
の機能を引き継ぎます。
これにより、__init__
メソッドなどの共通部分を新たに書かなくても使えます。def operate(self):
親クラスのoperate
メソッドをオーバーライドして、冷蔵庫専用の動作文に置き換えています。
ここでは「○○で冷蔵を開始します」というメッセージを返すように変更しました。- このように、それぞれの家電に合った動作を上書きすることで、同じ「operate」というメソッド名でも違った挙動を実現できます。
複数の家電をまとめて操作結果を表示する処理
# 家電製品のリストを作成し、それぞれの操作を出力します appliances = [WashingMachine("洗濯機"), Refrigerator("冷蔵庫")] # 各家電製品の操作を順に出力 for appliance in appliances: print(appliance.operate()) # 出力:洗濯機で洗濯を開始します, 冷蔵庫で冷蔵を開始します
この部分では、作成したクラスを使って実際に動作させています。
appliances = [WashingMachine("洗濯機"), Refrigerator("冷蔵庫")]
ここで、WashingMachine
とRefrigerator
のインスタンス(実体)を作り、リストappliances
に入れています。
それぞれ"洗濯機"
と"冷蔵庫"
がname
引数として渡されます。for appliance in appliances:
リスト内の家電オブジェクトを1つずつ取り出して、変数appliance
に代入します。print(appliance.operate())
各オブジェクトのoperate()
メソッドを呼び出して結果を表示します。
ここで重要なのは、同じoperate()
メソッド名でも、クラスごとにオーバーライドされているため、洗濯機では「洗濯を開始します」、冷蔵庫では「冷蔵を開始します」と異なるメッセージが表示される点です。
これが**ポリモーフィズム(多態性)**の典型的な例です。
オーバーライドの疑問解消|FAQと用語のまとめ
初心者がつまずきやすいポイントをFAQとしてまとめ、またよく使う専門用語をわかりやすく整理しました。
理解を深めたいときや、ふと疑問に感じたときに役立ててください。
FAQ|オーバーライドに関するよくある質問
- Q1. オーバーライドと継承の違いは何ですか?
-
継承は親クラスの機能を受け継ぐ仕組みで、オーバーライドはその機能を子クラスで再定義することを指します。
- Q2. オーバーライドする際の注意点は?
-
メソッド名を完全に一致させる必要があります。また、親クラスのメソッドを維持したい場合は
super()
を活用します。
- Q3. オーバーライドはクラス間で自由にできますか?
-
同じ名前のメソッドが親クラスに存在する場合に限り、子クラスでオーバーライドが有効になります。
Python用語集|オーバーライドに関する用語一覧
今回の記事で出てきた用語・関数などを一覧で紹介します。
このサイトに出てくる 全てのPython用語をまとめた用語集 も活用してください。