# ch01 — 継承 (extends)

Source: https://php-school.pages.dev/topics/class-advanced/ch01-inheritance/
Site: AIと学ぶPHPの学校 (https://php-school.pages.dev)
Lesson: クラスの応用
Level: L3

Reference (official): https://www.php.net/manual/ja/language.oop5.inheritance.php

## 本文

# ch01 — 継承 (extends)

## なぜ継承が要るか

`User` と `AdminUser` は **9 割同じ機能** を持つ。`email` / `login()` は両方に必要で、`AdminUser` だけが追加で `deleteAll()` を持つ。これを 2 つのクラスに **コピペで書くと、ログイン処理を直したいときに 2 箇所直す** ことになる。継承はこの重複を吸収する仕組み。

## extends の書き方

`class 子 extends 親` と書くと、親のプロパティとメソッドをそのまま引き継げる。

```php
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 親` で親クラスのプロパティとメソッドを引き継げる
- 子クラスで新しいメソッドを追加できる
- 「共通機能は親、権限固有の機能は子」という分け方を理解する

## 所要時間

スライド 5 分 + ドリル 1 問 = **12 分**

## ドリル

| no | 内容 |
|---|---|
| 01 | `User` を継承した `AdminUser` で `deleteAll()` を追加する |

## 採点

```bash
php scripts/grade.php topics/class-advanced/ch01-inheritance/drill/01-extend/
```

## 関連チャプター

- [`../../08-class/ch01-class-def`](../../08-class/ch01-class-def/) — クラス定義 (前提)
- [`ch02-override`](../ch02-override/) — 親メソッドの上書き
- [`ch03-parent-call`](../ch03-parent-call/) — `parent::` で親を呼ぶ
- [`ch04-abstract`](../ch04-abstract/) — 継承前提の抽象クラス

## スライド

---
marp: true
theme: dojo
paginate: true
size: 16:9
---

<!--
LLM_CONTEXT:
  Lesson 9 / Chapter 1
  目的: extends で親クラスを継承し、ユーザーロール (管理者 / 一般) で共通処理を親に、固有処理を子にまとめられるようにする
  題材: User (親) / AdminUser (子・deleteAll() を追加で持つ) / GuestUser (子・閲覧のみ)。Web 案件で頻出する「ロール別の挙動分岐」を継承で表現する
  扱わない: オーバーライド (ch02) / parent:: 呼び出し (ch03) / abstract (ch04) / interface (ch05) / static (ch06) / 実際の認証プロトコル
  読み上げ時間目安: 4 分半〜5 分
-->

# 継承 (extends)

Lesson 9 / Chapter 1

---

## ゴール

ユーザーの種類 (管理者 / 一般) ごとにクラスを分けたい。

```
User (親)         ← 共通: name, login()
 ├── AdminUser    ← 管理者だけ: deleteAll()
 └── GuestUser    ← 閲覧のみ
```

共通部分を **親にまとめる**、固有部分を **子に書く** ができるようにする。

---

## 似たクラスを 2 つ書くと重複する

```php
<?php
class AdminUser {
    public string $name;
    public function login() {
        echo "{$this->name} がログインした\n";
    }
}

class GuestUser {
    public string $name;
    public function login() {
        echo "{$this->name} がログインした\n";
    }
}
```

- `name` も `login()` も同じ
- 後から仕様変更すると **両方** 直す必要がある

---

## `extends` で共通部分を親クラスにまとめる

```php
<?php
class User {
    public string $name;
    public function login() {
        echo "{$this->name} がログインした\n";
    }
}

class AdminUser extends User {
}
```

- `User` を **親クラス** (スーパークラス)
- `AdminUser` を **子クラス** (サブクラス)
- 子は親の `name` と `login()` をそのまま使える

---

## 継承したメソッドを呼べる

```php
<?php
$u = new AdminUser();
$u->name = "tanaka";
$u->login();
```

実行結果:

```
tanaka がログインした
```

- `AdminUser` には `login()` を書いていないが、親 `User` のものが使える
- プロパティ `name` も同様

---

## 子クラスで新しいメソッドを追加できる

```php
<?php
class AdminUser extends User {
    public function deleteAll() {
        echo "{$this->name} が全データを削除した\n";
    }
}

$u = new AdminUser();
$u->name = "tanaka";
$u->login();       // 親から継承
$u->deleteAll();   // 子で追加 (管理者だけの操作)
```

- 子クラスにしか無いメソッドは、親 (`User`) や別の子 (`GuestUser`) では呼び出せない
- 本番では権限チェックも別途必要だが、ここではクラスでの分離に集中する

---

## 継承は「共通 → 親、固有 → 子」

```
User (親)
  ├── name
  └── login()
     ↑ 継承
AdminUser (子)
  └── deleteAll()    ← 管理者だけ持つ
GuestUser (子)
  └── (閲覧のみ・追加メソッドなし)
```

- 共通部分を親に置けば、変更が 1 箇所で済む
- 子クラスは「親 + 自分の追加分」を持つ

---

## このチャプターでできるようになること

✅ `class 子 extends 親` で継承できる
✅ 親クラスのプロパティ・メソッドを子で使える
✅ 子クラス独自のメソッドを追加できる
✅ ロール別 (管理者 / 一般) の共通処理を親にまとめる発想ができる

→ ドリルへ
