【PHP】Lesson5-6:メソッドをオーバーライドしよう

ながみえ

一つ前のレッスンでは クラスの継承 について学習しました。

今回は メソッドのオーバーライド について見ていきましょう。

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におけるメソッドのオーバーライドは以下のように記述します。

class 親クラス名 {					// 親クラスの定義
    public function メソッド名() {	// 継承させたいメソッド
        // このメソッドの処理内容
    }
}
class 子クラス名 extends 親クラス名 {	// 親クラスを継承した子クラスの定義
    public function メソッド名() {	// 親クラス内のメソッドと同名で定義してオーバーライド
        // 親クラスとは違う処理内容
    }
}

$変数1 = new 親クラス名();	// 親クラスのインスタンス生成
$変数1->メソッド名();		// 親クラスのメソッドの処理内容

$変数2 = new 子クラス名();	// 子クラスのインスタンス生成
$変数2->メソッド名();		// 子クラスでオーバーライドされた処理内容
  • 継承extends キーワードで親クラスを継承します。
  • オーバーライド:親クラスと同じ名前のメソッドを子クラスで再定義します。
  • アクセス修飾子:メソッドのアクセス修飾子(public など)は一致する必要があります。

オーバーライドの実例|親クラス・子クラスの連携サンプル

実際に親クラスの機能を利用しつつ、子クラスで追加処理を行うコードの例を示します。

また、PHPでは parent::メソッド名() を使って親クラスのメソッドをそのまま呼び出すことも可能です。

これにより親クラスの機能を引き継ぎながら、新しい処理を追加することが可能です。

<?php
class Animal {						// 親クラスの定義
    public function makeSound() {	// 親クラスのメソッド
        echo "何か音を出します。" . PHP_EOL;
    }
}
class Dog extends Animal {			// 子クラスの定義
    public function makeSound() {	// オーバーライドして追加処理を定義
        parent::makeSound();		// 親クラスのメソッドをそのまま呼び出し
        echo "ワンワン!" . PHP_EOL;	// 子クラスの独自機能
    }
}
class Cat extends Animal {			// 子クラスの定義
    public function makeSound() {	// オーバーライドして追加処理を定義
        parent::makeSound();		// 親クラスのメソッドをそのまま呼び出し
        echo "にゃー!" . PHP_EOL;	// 子クラスの独自機能
    }
}

$dog = new Dog();	// インスタンス生成
$dog->makeSound();	// 子クラスでオーバーライドしたメソッドの呼び出し
$cat = new Cat();	// インスタンス生成
$cat->makeSound();	// 子クラスでオーバーライドしたメソッドの呼び出し
  • parent::メソッド名() を使うことで親クラスのメソッドを呼び出しています。
  • 子クラスで親クラスの機能を引き継ぎながら、独自の機能を追加しています。

このコードを実行すると、以下のように出力されます。

何か音を出します。
ワンワン!
何か音を出します。
にゃー!

まとめ|オーバーライドで広がるクラス設計の自由度

オーバーライドの仕組みと書き方を学ぶことで、親クラスのメソッドを子クラスで自由に再定義できるようになりました。

これにより既存の機能を活かしつつ、目的に合わせて柔軟にクラスの動作をカスタマイズできるようになります。

また、parentキーワードの使い方も理解できたことで、親クラスと子クラスの連携もスムーズに行えるようになったはずです。

オーバーライドをマスターすることで、より実践的で応用力のあるオブジェクト指向プログラミングが可能になります。

次のレッスンでも、一歩一歩スキルを磨いていきましょう!

演習問題|オーバーライドで乗り物クラスを拡張しよう

乗り物が移動するプログラムを作成しましょう。

このプログラムでは親クラス「乗り物」に移動する動作を定義し、子クラス「車」と「船」でその動作をカスタマイズします。

具体的には車は「道路を走る」、船は「海を進む」という追加の動作を行います。

親クラスの動作も残しながら、子クラス独自の振る舞いを定義するには メソッドのオーバーライド を使います。

この練習問題ではオーバーライドの基本を理解し、継承を利用したコードの作成を学びましょう。

この演習の要件

以下の要件に従ってコードを完成させてください。

  1. 親クラス「Vehicle」を定義すること。
    • 「move」メソッドを作成し、「乗り物が移動します。」と出力すること。
  2. 子クラス「Car」を定義すること。
    • 親クラス「Vehicle」を継承すること。
    • 「move」メソッドをオーバーライドし、以下の2つの処理を行うこと。
      1.親クラスの「move」メソッドを呼び出すこと。
      2.「車が道路を走ります。」と出力すること。
  3. 子クラス「Ship」を定義すること。
    • 親クラス「Vehicle」を継承すること。
    • 「move」メソッドをオーバーライドし、以下の2つの処理を行うこと。
      1.親クラスの「move」メソッドを呼び出すこと。
      2.「船が海を進みます。」と出力すること。
  4. インスタンスを作成してテストすること。
    • 「Car」と「Ship」のインスタンスを作成し、それぞれの「move」メソッドを呼び出して動作を確認すること。

ただし、以下のような実行結果となること。

乗り物が移動します。
車が道路を走ります。
乗り物が移動します。
船が海を進みます。

解き方のヒント

1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。

Q
ヒント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メソッドを呼び出し

Q
ヒント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(); // 出力例

このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。

演習問題の答え合わせ

この問題の正解コードとその解説は以下の通りです。

クリックして開いて確認してください。

Q
正解コード
<?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(); // 出力例
Q
正解コードの解説

コードをブロックごとに分割して解説します。

親クラス「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;
    }
}
  1. 継承extends Vehicle により、「Car」クラスは「Vehicle」クラスの機能を継承します。これにより、親クラスで定義されたメソッドやプロパティを利用できます。
  2. メソッドのオーバーライド
    • 親クラスと同じ名前のメソッド move() を再定義しています。
    • これにより、親クラスのメソッドをカスタマイズできます。
  3. 親クラスのメソッド呼び出し
    • parent::move() を使うことで、親クラスの move() をそのまま呼び出します。
    • これにより、親クラスの機能を維持しつつ追加処理を行えます。
  4. 追加処理
    • 継承された機能に加え、「車が道路を走ります。」というメッセージを出力します。

子クラス「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();
  1. インスタンス作成new Car()new Ship() によって、クラスのインスタンス(オブジェクト)を作成します。
  2. メソッド呼び出し
    • $car->move() により、「Car」クラスの move() メソッドが実行されます。
    • $ship->move() により、「Ship」クラスの move() メソッドが実行されます。
  3. 結果の出力:それぞれの動作に応じたメッセージが出力されます。
もっと分かりやすい学習サイトにするために

この記事を読んで「ここが分かりにくかった」「ここが難しかった」等の意見を募集しています。

世界一わかりやすいPHP学習サイトにするため、ぜひ 問い合わせフォーム からご意見下さい。

<<前のページ

学習記事一覧

次のページ>>

記事URLをコピーしました