ITHACK
~ みんなのIT部門 ~

【PHP】オーバーロード – オーバーロードを可変長引数リストで実現する

プログラミングではオーバーロードと呼ばれる仕組みがありますが、PHPでオーバーロードはサポートされていません。

しかし、オーバーロードを使った設計にしたい場合があると思います。

ここではオーバーロードとPHPでの実現方法について解説します。

  • オーバーロード

  • PHPのオーバーロード実現方法

オーバーロードとは

オーバーロードとはクラスのメソッドで引数の数が異なる同じ名前のメソッドを複数定義することです。

PHPで実現する

初頭で述べた通り、PHPはオーバーロードをサポートしていません。
そのため、PHPでオーバーロードを実現するには、可変長引数リストと呼ばれる仕組みを利用します。

可変長引数リスト

可変長引数リストは引数で使う仕組みです。
可変長引数リストを使うことで、任意の数だけ引数を与えれるようになります。

基本構文

可変長引数リストの基本構文は次のようになります。

function メソッド名( ...$可変長引数リスト名 ) {
    // 処理・・・・・・・
    return $変数名または値;
}

可変長引数リストはドットを3つ繋げ、続いて変数名を記述し、関数またはメソッドの引数で使用できます。

サンプルコード

PHPでオーバーロードする場合の可変長引数リストを使ったサンプルコードをご覧ください。

<?php

// クラス
class Calculator {
    
    // 計算と結果を出力
    public function execute(...$data) {
        $total = null;
        if( isset($data[0]) ) {
            $total = $data[0];
        }
        if( isset($data[1]) ) {
            $total += $data[1];
        }
        if( isset($data[2]) ) {
            $total *= $data[2];
        }
        echo "total : {$total}\n";
    }
    
}

// インスタンスの生成
$calc = new Calculator();

// 計算結果を出力
$calc->execute(1, 2, 3);

?>
total: 9

引数の数によって計算を実行するプログラムです。

各コードの概要は次にようになります。

行数 概要
4〜21 Calculatorクラスの定義。
24 Calculatorクラスのインスタンスを生成し、$calcに代入。
27 $calcのexecuteメソッドを実行。

7行目のexecuteメソッドの引数で可変長引数リストを使用しています。
可変長引数リストは呼び出し元の引数で与えた値を、変数に配列として記憶します。

メソッド内では配列の数に合わせて処理を実行し、オーバーロードのような設計を実現しています。

演習問題

問題1

次の実行結果になる会計クラスを扱うプログラムを作成してください。
なお、下記条件を満たすものとします。

  • 会計クラス(Bill)を作成する
  • 会計クラスはcalcメソッドを持ち、引数で与えられた複数料金の合計金額を出力する
  • calcメソッドの引数は可変長引数リストとする
  • calcメソッドに与えられた引数が3つ以上の場合、合計金額を5%割引する
  • calcメソッドを2回呼び出し、各呼び出しの引数は次の通りとする
    1回目 : 1000, 2300
    2回目 : 1000, 2300, 3500
合計金額 : 3300円
合計金額 : 6460円

問題2

次の実行結果になる自己紹介クラスを扱うプログラムを作成してください。
なお、下記条件を満たすものとします。

  • 自己紹介クラス(SelfIntroduction)を作成する
  • 自己紹介クラスはexecuteメソッドを持ち、引数で与えられた値を元に自己紹介を出力する
  • executeメソッドの引数は可変長引数リストとし、各引数は次の通りとする
    第1引数 : 名前
    第2引数 : 年齢
    第3引数 : 趣味
  • 実行結果になるようにexecuteメソッドを使用する
名前 : Watanabe You
年齢 : 16
趣味 : Training

まとめ

PHPはオーバーロードをサポートしていませんが、可変長引数リストを使用することで似た実装ができます。

ただ、PHPで正式にサポートされていない=推奨していないということかもしれないので、設計や動作を考慮して使いましょう。