抽象クラス
抽象クラスは
abstract classキーワードでクラスを定義するabstract定義されたメソッドを含む
たとえば以下のクラスは、RPGのキャラクターをイメージしていて、
- 固有の名前を持つ
- 名前を返す
publicメソッドを持つ attack()というabstract宣言されたpublicメソッドを持つ
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?php abstract class CharacterClass { private $name; abstract public function attack(); public function __construct($name) { $this->name = $name; } public function getName() { return $this->name; } } |
このクラスからインスタンスを生成しようとすると、Cannot instantiate abstract class CharacterClassとエラーになる。
抽象クラスの継承
先の抽象クラスCharacterClassを継承して、以下の2つのクラスを定義する。
|
1 2 3 4 5 6 7 8 9 10 11 |
class Swordfighter extends CharacterClass { public function attack() { echo $this->getName() . "は剣で切りかかった!\n"; } } class Wizard extends CharacterClass { public function attack() { echo $this->getName() . "は攻撃呪文を唱えた!\n"; } } |
こうすると、Swordfighterクラス、Wizardクラスのインスタンスを生成することができる。
|
1 2 3 4 5 6 7 8 |
$arthur = new Swordfighter('アーサー'); $harry = new Wizard('ハリー'); $arthur->attack(); $harry->attack(); // アーサーは剣で切りかかった! // ハリーは攻撃呪文を唱えた! |
ポリモーフィズム
先の2つのクラス(Swordfighter、Wizard)のインスタンスを、以下のように配列にしてattack()メソッドを実行してみる。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$party_members = []; $party_members[] = new Swordfighter('アーサー'); $party_members[] = new Wizard('ハリー'); $party_members[] = new Wizard('セイメイ'); $party_members[] = new Swordfighter('コジロー'); foreach ($party_members as $member) { $member->attack(); } // アーサーは剣で切りかかった! // ハリーは攻撃呪文を唱えた! // セイメイは攻撃呪文を唱えた! // コジローは剣で切りかかった! |
配列の各要素が具体にどのクラスかを指定しなくても、それぞれのクラスに応じたattack()メソッドが適切に呼ばれている(ポリモーフィズム)。
抽象クラスとポリモーフィズム
- 抽象クラスは
abstractメソッドを含む - 抽象クラスを継承したクラスのうち、インスタンスを生成するクラスでは、必ず
abstractメソッドを実装しなければならない - 実行時に
abstractメソッドに対応したメソッドを呼び出すと、インスタンスのクラスを逐一確認しなくても、そのインスタンスのクラスに応じたメソッドが実行される - したがって、
abstractメソッドの機能の実装は各継承クラスで責任を持ち、それを呼び出す側でケアする必要はない(例外処理などを除けば)