なぜ継承が要るか
User と AdminUser は 9 割同じ機能 を持つ。email / login() は両方に必要で、AdminUser だけが追加で deleteAll() を持つ。これを 2 つのクラスに コピペで書くと、ログイン処理を直したいときに 2 箇所直す ことになる。継承はこの重複を吸収する仕組み。
extends の書き方
class 子 extends 親 と書くと、親のプロパティとメソッドをそのまま引き継げる。
class User {
public string $email;
public function login(): void {
echo "{$this->email} がログインしました\n";
}
}
class AdminUser extends User {
public function deleteAll(): void {
echo "{$this->email} が全データを削除しました\n";
}
}AdminUser は login() を書いていないのに呼べる。
is-a 関係で使う
継承の判断基準は 「子は親の役割を全部果たせるか」。AdminUser is a User (管理者もユーザー) は自然なので OK。一方 Order is a PaymentGateway (注文は決済ゲートウェイ) は不自然なので、こちらはプロパティで PaymentGateway を持つ「has-a 関係」にする。
PHP は単一継承
PHP では 1 つのクラスは親を 1 つしか持てない (extends A, B は書けない)。複数の能力を組み合わせたいときは、後の章で扱う インターフェース (ch05) で契約を複数実装する形にする。
深い継承は避ける
継承は強力だが、親を直すとすべての子に波及する副作用も大きい。現代では 1〜2 段で済ませる 設計が主流。3 段以上の継承ツリーを作る前に「これは継承でいいのか」を疑うのがよい。
学習目標
class 子 extends 親で親クラスのプロパティとメソッドを引き継げる- 子クラスで新しいメソッドを追加できる
- 「共通機能は親、権限固有の機能は子」という分け方を理解する
ドリル
| no | 内容 |
|---|---|
| 01 | User を継承した AdminUser で deleteAll() を追加する |
📝 演習: ドリル 01 — User を継承した AdminUser
やること
User クラスを定義してください。
- プロパティ
email(string) - メソッド
login()は"{email} がログインしました"を 1 行出力する
次に User を継承した AdminUser クラスを定義してください。
- メソッド
deleteAll()は"{email} が全データを削除しました"を 1 行出力する
最後に AdminUser のインスタンスを作って email に "admin@example.com" を入れ、login() と deleteAll() を順に呼んでください。
期待される出力
admin@example.com がログインしました
admin@example.com が全データを削除しました
補足: 実務ではパスワード照合・セッション発行・権限チェックが入りますが、ここでは「継承で機能を引き継ぐ」一点だけにフォーカスします。
ヒント
class AdminUser extends User { ... }$a = new AdminUser();$a->email = "admin@example.com";- 親の
login()はAdminUserに書かなくても呼べる