抽象クラス
抽象クラスは
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
メソッドの機能の実装は各継承クラスで責任を持ち、それを呼び出す側でケアする必要はない(例外処理などを除けば)