【PHP】Lesson5−6:メソッドのオーバーライドを基礎から学ぼう|親クラスの再定義方法

オブジェクト指向プログラミングでは、親クラスから継承したメソッドを子クラスで上書きする機能を 「メソッドのオーバーライド」 と呼びます。
これにより継承された機能をカスタマイズして再利用できるため、柔軟なプログラム設計が可能になります。
PHPでは親クラスと同じ名前のメソッドを子クラスで再定義することでオーバーライドを実現します。
Lesson1:基礎文法編
Lesson2:制御構造編
Lesson3:関数編
Lesson4:データ構造編
Lesson5:クラス編
・Lesson5-1:クラスを定義しよう
・Lesson5-2:コンストラクタを理解しよう
・Lesson5-3:アクセス修飾子とカプセル化を理解しよう
・Lesson5-4:クラスメンバを理解しよう
・Lesson5-5:クラスの継承を理解しよう
・Lesson5-6:メソッドのオーバーライドを理解しよう ◁今回はココ
・Lesson5-7:抽象クラスを理解しよう
・Lesson5-8:インターフェースを理解しよう
・Lesson5-9:トレイトを理解しよう
・確認問題5-1:モンスター捕獲ゲームを作ろう
・確認問題5-2:マインスイーパを作ろう
PHPのメソッドオーバーライドとは?|親クラスをカスタマイズする手法


メソッドのオーバーライドとは、親クラスで定義されたメソッドを子クラスで再定義し、動作を変更する手法です。
たとえば親クラスに「基本的な動作」を記述し、子クラスでは「具体的な処理」を追加したい場合に役立ちます。
PHPではparent::メソッド名()
を使って親クラスのメソッドを呼び出すこともできます。
これにより親クラスの機能を引き継ぎながら、新しい処理を追加することが可能です。
メソッドの再定義方法|PHPにおけるオーバーライドの書き方
PHPにおけるメソッドのオーバーライドは以下のように記述します。
class ParentClass { // 親クラスのメソッド public function greet() { echo "こんにちは!" . PHP_EOL; } } class ChildClass extends ParentClass { // 子クラスでオーバーライド public function greet() { echo "Hello!" . PHP_EOL; } } // インスタンス化してメソッドを呼び出す $parent = new ParentClass(); $parent->greet(); // 出力: こんにちは! $child = new ChildClass(); $child->greet(); // 出力: Hello!
- 継承:
extends
キーワードで親クラスを継承します。 - オーバーライド:親クラスと同じ名前のメソッドを子クラスで再定義します。
- アクセス修飾子:メソッドのアクセス修飾子(
public
など)は一致する必要があります。
オーバーライドの実例解説|親クラスと子クラスの連携方法
次に親クラスの機能を利用しつつ、子クラスで追加処理を行う例を示します。
class Animal { // 親クラスのメソッド public function makeSound() { echo "何か音を出します。" . PHP_EOL; } } class Dog extends Animal { // オーバーライドして追加処理を定義 public function makeSound() { parent::makeSound(); // 親クラスのメソッドを呼び出し echo "ワンワン!" . PHP_EOL; } } $dog = new Dog(); $dog->makeSound(); /* 出力: 何か音を出します。 ワンワン! */
parent::メソッド名()
を使うことで親クラスのメソッドを呼び出しています。- 子クラスで親クラスの機能を引き継ぎながら、独自の機能を追加しています。
オーバーライドのまとめ|親クラスの再利用と柔軟性を活かすには
PHPのメソッドのオーバーライドは、親クラスの機能を再利用しながら独自の振る舞いを追加する際に非常に役立ちます。
- 基本構文:親クラスと同じ名前のメソッドを子クラスで再定義します。
- アクセス修飾子の一致:親クラスと子クラスのメソッドでアクセス修飾子を一致させる必要があります。
parent::
キーワード:親クラスのメソッドを呼び出すことで、機能を拡張できます。
この機能を活用することで、保守性や再利用性に優れたプログラムを設計できます。
演習問題|オーバーライドで乗り物クラスを拡張しよう

乗り物が移動するプログラムを作成しましょう。
このプログラムでは親クラス「乗り物」に移動する動作を定義し、子クラス「車」と「船」でその動作をカスタマイズします。
具体的には車は「道路を走る」、船は「海を進む」という追加の動作を行います。
親クラスの動作も残しながら、子クラス独自の振る舞いを定義するには メソッドのオーバーライド を使います。
この練習問題ではオーバーライドの基本を理解し、継承を利用したコードの作成を学びましょう。
この演習の要件
以下の要件に従ってコードを完成させてください。
- 親クラス「Vehicle」を定義すること。
- 「move」メソッドを作成し、「乗り物が移動します。」と出力すること。
- 子クラス「Car」を定義すること。
- 親クラス「Vehicle」を継承すること。
- 「move」メソッドをオーバーライドし、以下の2つの処理を行うこと。
1.親クラスの「move」メソッドを呼び出すこと。
2.「車が道路を走ります。」と出力すること。
- 子クラス「Ship」を定義すること。
- 親クラス「Vehicle」を継承すること。
- 「move」メソッドをオーバーライドし、以下の2つの処理を行うこと。
1.親クラスの「move」メソッドを呼び出すこと。
2.「船が海を進みます。」と出力すること。
- インスタンスを作成してテストすること。
- 「Car」と「Ship」のインスタンスを作成し、それぞれの「move」メソッドを呼び出して動作を確認すること。
ただし、以下のような実行結果となること。
乗り物が移動します。 車が道路を走ります。 乗り物が移動します。 船が海を進みます。
解き方のヒント
1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。
- ヒント1【コードの構成を見る】
-
正解のコードは上から順に以下のような構成となっています。
(※下記の□はコード内のインデントを表しています)1:クラスVehicleの定義
□ メソッドmoveの定義
□ □ 「乗り物が移動します。」を出力
2:クラスCarの定義(Vehicleを継承)
□ メソッドmoveの定義(オーバーライド)
□ □ 親クラスのmoveメソッドを呼び出し
□ □ 「車が道路を走ります。」を出力
3:クラスShipの定義(Vehicleを継承)
□ メソッドmoveの定義(オーバーライド)
□ □ 親クラスのmoveメソッドを呼び出し
□ □ 「船が海を進みます。」を出力
4:変数$carにクラスCarのインスタンスを代入
5:変数$carのmoveメソッドを呼び出し
6:変数$shipにクラスShipのインスタンスを代入
7:変数$shipのmoveメソッドを呼び出し
- ヒント2【穴埋め問題にする】
-
以下のコードをコピーし、コメントに従ってコードを完成させて下さい。
<?php // 親クラス「乗り物」を定義 class Vehicle { // 移動方法を表示するメソッド public function move() { echo "乗り物が移動します。" . PHP_EOL; } } // 子クラス「車」を定義(親クラスVehicleを継承) class Car extends Vehicle { /* 【穴埋め問題1】ここでメソッドmoveをオーバーライドし、 親クラスのmoveメソッドを呼び出した後に「車が道路を走ります。」と出力するコードを書いてください。 */ } // 子クラス「船」を定義(親クラスVehicleを継承) class Ship extends Vehicle { /* 【穴埋め問題2】ここでメソッドmoveをオーバーライドし、 親クラスのmoveメソッドを呼び出した後に「船が海を進みます。」と出力するコードを書いてください。 */ } // インスタンスの作成とテスト $car = new Car(); $car->move(); // 出力例 $ship = new Ship(); $ship->move(); // 出力例
このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。
演習問題の答え合わせ
この問題の正解コードとその解説は以下の通りです。
クリックして開いて確認してください。
- 正解コード
-
<?php // 親クラス「乗り物」を定義 class Vehicle { // 移動方法を表示するメソッド public function move() { echo "乗り物が移動します。" . PHP_EOL; } } // 子クラス「車」を定義(親クラスVehicleを継承) class Car extends Vehicle { // メソッドのオーバーライド public function move() { // 親クラスのmoveメソッドを呼び出し parent::move(); // 子クラス独自の処理を追加 echo "車が道路を走ります。" . PHP_EOL; } } // 子クラス「船」を定義(親クラスVehicleを継承) class Ship extends Vehicle { // メソッドのオーバーライド public function move() { // 親クラスのmoveメソッドを呼び出し parent::move(); // 子クラス独自の処理を追加 echo "船が海を進みます。" . PHP_EOL; } } // インスタンスの作成とテスト $car = new Car(); $car->move(); // 出力例 $ship = new Ship(); $ship->move(); // 出力例
- 正解コードの解説
-
コードをブロックごとに分割して解説します。
親クラス「Vehicle」の定義
class Vehicle { public function move() { echo "乗り物が移動します。" . PHP_EOL; } }
- クラスの定義:
class Vehicle
で親クラス「Vehicle」を定義します。 - メソッドの作成:
move()
メソッドは、移動動作を表現するための基本メソッドです。 - 出力処理:
echo
を使って「乗り物が移動します。」と表示します。 - 改行の処理:改行には
PHP_EOL
を使用しています。これにより、プラットフォームに依存しない改行が可能になります。
子クラス「Car」の定義
class Car extends Vehicle { public function move() { parent::move(); echo "車が道路を走ります。" . PHP_EOL; } }
- 継承:
extends Vehicle
により、「Car」クラスは「Vehicle」クラスの機能を継承します。これにより、親クラスで定義されたメソッドやプロパティを利用できます。 - メソッドのオーバーライド:
- 親クラスと同じ名前のメソッド
move()
を再定義しています。 - これにより、親クラスのメソッドをカスタマイズできます。
- 親クラスと同じ名前のメソッド
- 親クラスのメソッド呼び出し:
parent::move()
を使うことで、親クラスのmove()
をそのまま呼び出します。- これにより、親クラスの機能を維持しつつ追加処理を行えます。
- 追加処理:
- 継承された機能に加え、「車が道路を走ります。」というメッセージを出力します。
子クラス「Ship」の定義
class Ship extends Vehicle { public function move() { parent::move(); echo "船が海を進みます。" . PHP_EOL; } }
- 継承:
extends Vehicle
により、「Ship」クラスは「Vehicle」クラスの機能を継承します。 - メソッドのオーバーライド:親クラスと同じ名前のメソッド
move()
を再定義しています。 - 親クラスのメソッド呼び出し:
parent::move()
を使って、親クラスのメソッドを呼び出します。 - 追加処理:親クラスの処理に加え、「船が海を進みます。」というメッセージを表示します。
インスタンスの作成と実行
$car = new Car(); $car->move(); $ship = new Ship(); $ship->move();
- インスタンス作成:
new Car()
とnew Ship()
によって、クラスのインスタンス(オブジェクト)を作成します。 - メソッド呼び出し:
$car->move()
により、「Car」クラスのmove()
メソッドが実行されます。$ship->move()
により、「Ship」クラスのmove()
メソッドが実行されます。
- 結果の出力:それぞれの動作に応じたメッセージが出力されます。
- クラスの定義:
まとめ
このコードでは、PHPにおける 「メソッドのオーバーライド」 の使い方を学びました。
- オーバーライドのポイント:親クラスと同じ名前のメソッドを子クラスで再定義し、独自の処理を追加できます。
- 親クラスのメソッドを活用:
parent::メソッド名()
を使うことで、親クラスの機能を引き継ぎつつ追加処理を行うことができます。 - 継承による拡張性:親クラスで基本的な処理を定義し、子クラスごとに振る舞いを変えることで、プログラムの柔軟性や再利用性が向上します。
このコードを理解することで、オブジェクト指向プログラミングの基本概念である 継承 と オーバーライド をしっかりと身につけることができます。
他のクラス設計にも応用できるので、ぜひ色々な例を試してみてください!