【PHP】レッスン5-06:メソッドをオーバーライドしよう

記事内に商品プロモーションを含む場合があります

この記事で学べる知識:オーバーライド

この記事の練習問題を解くために必要な知識:
基礎文法・制御構造・関数・データ構造(レッスン1~4)クラスの定義と使用コンストラクタアクセス修飾子とカプセル化クラスメンバクラスの継承メソッドのオーバーライド抽象クラスインターフェーストレイト

<<前のページ PHP記事一覧 次のページ>>

PHPの「オーバーライド」とは

この章ではPHPにおける「オーバーライド」の意味や使い方を学習します。用語の解説が不要な方はここをクリックして練習問題へ飛びましょう。




オブジェクト指向プログラミングでは、親クラスから継承したメソッドを子クラスで上書きする機能を 「メソッドのオーバーライド」 と呼びます。

これにより継承された機能をカスタマイズして再利用できるため、柔軟なプログラム設計が可能になります。

PHPでは親クラスと同じ名前のメソッドを子クラスで再定義することでオーバーライドを実現します。

【初心者向け】PHPのオブジェクト指向を分かりやすくまとめた概念図。 特にクラスの継承、オーバーライド、抽象クラス、インターフェース、トレイトの関係性を視覚的に理解できるようまとめている。

メソッドのオーバーライドとは?

メソッドのオーバーライドとは、親クラスで定義されたメソッドを子クラスで再定義し、動作を変更する手法です。

たとえば親クラスに「基本的な動作」を記述し、子クラスでは「具体的な処理」を追加したい場合に役立ちます。

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

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

オーバーライドの基本構文

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:: キーワード:親クラスのメソッドを呼び出すことで、機能を拡張できます。

この機能を活用することで、保守性や再利用性に優れたプログラムを設計できます。

メソッドのオーバーライドの練習問題:乗り物の動きをカスタマイズしよう!

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

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

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

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

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

この問題の要件

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

  1. 親クラス「Vehicle」を定義すること。
    • 「move」メソッドを作成し、「乗り物が移動します。」と出力すること。
  2. 子クラス「Car」を定義すること。
    • 親クラス「Vehicle」を継承すること。
    • 「move」メソッドをオーバーライドし、以下の2つの処理を行うこと。
      1.親クラスの「move」メソッドを呼び出すこと。
      2.「車が道路を走ります。」と出力すること。
  3. 子クラス「Ship」を定義すること。
    • 親クラス「Vehicle」を継承すること。
    • 「move」メソッドをオーバーライドし、以下の2つの処理を行うこと。
      1.親クラスの「move」メソッドを呼び出すこと。
      2.「船が海を進みます。」と出力すること。
  4. インスタンスを作成してテストすること。
    • 「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;
    }
}
  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における 「メソッドのオーバーライド」 の使い方を学びました。

  • オーバーライドのポイント:親クラスと同じ名前のメソッドを子クラスで再定義し、独自の処理を追加できます。
  • 親クラスのメソッドを活用parent::メソッド名() を使うことで、親クラスの機能を引き継ぎつつ追加処理を行うことができます。
  • 継承による拡張性:親クラスで基本的な処理を定義し、子クラスごとに振る舞いを変えることで、プログラムの柔軟性や再利用性が向上します。

このコードを理解することで、オブジェクト指向プログラミングの基本概念である 継承オーバーライド をしっかりと身につけることができます。

他のクラス設計にも応用できるので、ぜひ色々な例を試してみてください!

<<前のページ PHP記事一覧 次のページ>>

この記事への質問・コメント

この記事を作成するにあたりAIを活用しています。

問題ないことは確認していますが、もし間違いや表現の違和感などありましたら、ご指摘頂けると大変助かります。






    PHPのテキスト&問題集トップへ戻る
    トップページへ戻る