PHP – 継承

設定

以下のようなクラス構成を考える。

  • RPGに出てくるようなキャラクターとして、剣士と魔法使いを考える
  • 共通点として、いずれも名前とエネルギーを持つ
  • 剣士特有の能力として、剣で切りかかって戦う動作ができる
  • 魔法使い特有の能力として、攻撃魔法を唱える動作ができる
  • それぞれの動作を行うと、それに応じたエネルギーが消費される

親クラス~汎化

キャラクターの種類によらず共通するものを、親クラスCharacterClassとしてまとめる。

  • privateなプロパティーとして、$name(名前)、$energy(エネルギー)を持つ
  • インスタンス生成時に名前を与えて生成し、エネルギーの初期値は職業によらず100
  • それぞれの値を得るpublicなゲッターを備えている
  • エネルギー値を変更するpublicメソッドを備えている
  • 自身の攻撃の番であることを表示するpublicメソッドを備えている

継承

CharacterClassクラスを継承し、剣士(Swordfighter)と魔法使いのクラスを定義する。

  • 戦士の動作メソッドattack()で剣で切りかかり、エネルギーを15消費する
  • 魔法使いの動作メソッドspell()で攻撃魔法を唱え、エネルギーを10消費する

剣士としてアーサー、魔法使いとしてハリーという名前でインスタンスを生成し、順番に2回ずつ攻撃させる。

メソッドのオーバーライド

CharacterClassクラスにshowTurn()メソッドを定義したが、これと同じ名前のメソッドをSwordfighterクラスとWizardクラスに定義する。

そして同じように実行すると以下のようになり、それぞれの子クラスで定義したshowTurn()が呼ばれて剣士・魔法使いと表示され、その後に親クラスのメソッドの表示がされている。

ここで行ったのがメソッドのオーバーライド。

  • 親クラスのメソッドと同じ名前のメソッドを子クラスで定義した場合、子クラスのメソッドが呼ばれる
  • 子クラスのメソッドの中でparent::メソッド名とすると、親クラスのメソッドが呼ばれる。

実行時のメソッドの探索順は以下の通り。

  1. 現在のクラスで該当するメソッドを探す
  2. 無ければ親クラスのメソッドを順次遡って探す
  3. parent::で呼ばれた場合、親クラスのメソッドを探す

コンストラクター

オーバーライド

上記のコードに更に変更を加えて、初期エネルギー値を戦士が100、魔法使いが80となるようにする。

まずCharacterClassのコンストラクターを変更して、$energyについても引数で値をあてるようにする。

そしてSwordfighterWizardそれぞれのクラスにコンストラクターを追加。インスタンス生成時には名前のみを指定し、それぞれのクラスに応じた初期エネルギー値を親クラスのコンストラクターに渡して、名前とともにセットする。

実行結果は以下の通り。

クラスの継承とコンストラクター/デストラクターについて

  • インスタンス生成時、子クラスのコンストラクターが見つからなければ、親クラスのコンストラクターが使われる
  • 子クラスのコンストラクターを定義した場合、暗黙では親クラスのコンストラクターは呼ばれない
  • から親クラスのコンストラクター/デストラクターを呼び出すときは、parent::_construct/__destructで呼び出す
  • 通常、子クラスのコンストラクターの中で
    • parent::constructor()はコードの最初に書く
    • parent::destructor()はコードの最後に書く

プロパティーのprivate宣言について

  • 親クラスのプロパティー$name$energyprivate宣言にしているので、継承した子クラスから直接はアクセスできない
    • このため、publicなメソッドを準備して、アクセスさせている
  • プロパティーをpublic宣言すると子クラスから$this->nameのようにアクセスできる
    • しかしpublic宣言すると、クラス外部で任意に名前やエネルギーの値を変更できてしまう
  • protected宣言にすれば、継承したクラスから$this->nameのようにアクセスできる
    • ここではプロパティーの変更を厳格にし、アクセスメソッドを準備しているのでprivateにした

 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です