# ch08 — final クラス / final メソッド

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

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

## 本文

# ch08 — final クラス / final メソッド

## 概要

`final` 修飾子は **「これ以上の拡張を禁止する」** ための宣言で、クラスに付ければ `extends` できなくなり、メソッドに付ければそのメソッドのオーバーライドができなくなる。`final class Config { ... }` と書けば誰も `Config` を継承して挙動を差し替えられず、`final public function save()` と書けば子クラスが `save()` を上書きすることを防げる。「ここは変えてほしくない」と意図を **コードで明示** できるのが `final` の役割になる。

なぜ拡張を禁止したいのかというと、**Liskov 置換原則 (LSP)** が守られない継承を未然に防ぐためだ。継承は強力だが、子クラスが親の前提を壊すように書かれると「親型として扱える」性質が崩れ、呼び出し側で予期しない動作になる。クラスを公開する側が「このクラスは継承を想定していない」と判断したなら、`final class` にしておくことで誤った継承を防げる。

実務的には **すべての公開クラスを最初から `final` にして、必要になったときだけ外す** という方針もよく採られる。クラスを継承可能にすると、後で内部実装を変えにくくなる (子クラスが内部メソッドに依存しているかもしれない) ので、迷ったら拡張を閉じる側に倒すという考え方だ。継承よりもインターフェース + コンポジションで拡張点を作る、というモダンな設計とも相性がよい。

## 学習目標

- `final class` は **継承を禁止** する
- `final function` はそのメソッドの **オーバーライドを禁止** する
- 「これ以上拡張させない」と意図を明示できる

## 所要時間

スライド 4 分 + ドリル 1 問 = **10 分**

## ドリル

| no | 内容 |
|---|---|
| 01 | `final class` を作って単一インスタンスを生成・出力する |

## 採点

```bash
php scripts/grade.php topics/class-advanced/ch08-final/drill/01-final-class/
```

## 関連チャプター

- [`ch01-inheritance`](../ch01-inheritance/) — 継承 (これを禁止する)
- [`ch02-override`](../ch02-override/) — オーバーライド (final で禁止できる)
- [`ch07-const`](../ch07-const/) — 不変なクラス定数との合わせ技

## スライド

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

<!--
LLM_CONTEXT:
  Lesson 9 / Chapter 8
  目的: final で継承・オーバーライドを禁止し、「これ以上拡張させない」を明示する
  扱わない: readonly / 名前空間 / autoload / 抽象との組み合わせ (abstract と final は共存不可)
  読み上げ時間目安: 3 分半〜4 分
-->

# final クラス / final メソッド

Lesson 9 / Chapter 8

---

## 継承されると困るクラスがある

```php
<?php
class Logger {
    public function log(string $msg) {
        echo "[LOG] $msg\n";
    }
}

class BadLogger extends Logger {
    public function log(string $msg) {
        // パスワードを画面に出してしまう実装に変えられてしまった!
        echo "[LEAK] $msg\n";
    }
}
```

- 継承できると、第三者にどんな振る舞いに変えられるか分からない
- セキュリティ上、改造を禁じたいときがある

---

## `final class` で継承を禁止

```php
<?php
final class Logger {
    public function log(string $msg) {
        echo "[LOG] $msg\n";
    }
}

class BadLogger extends Logger {   // ❌ Fatal error
}
```

- `class` の前に `final` を付ける
- このクラスを継承しようとした瞬間にエラー
- 「これは設計が完成しているので、改造禁止」という意思表示

---

## `final` メソッドはオーバーライドを禁止

```php
<?php
class Logger {
    final public function log(string $msg) {
        echo "[LOG] $msg\n";
    }
}

class TimedLogger extends Logger {
    public function log(string $msg) {   // ❌ Fatal error
        echo "...\n";
    }
}
```

- クラス自体は継承できる
- でも **特定のメソッドだけ** はオーバーライドさせない
- 「ここの動きは絶対変えるな」という保護

---

## 使い分け

|  | やりたいこと |
|---|---|
| `final class` | クラスごと拡張不可にする |
| `final function` | クラスは継承可、でもこのメソッドだけ変えさせない |

「外部に公開する設計済みクラス」「金額計算など壊されたら困る処理」に有効。

---

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

✅ `final class` で継承を禁止できる
✅ `final function` でオーバーライドを禁止できる
✅ 「拡張されたら困る箇所」に意図を明示できる

→ ドリルへ
