概要

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

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

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

学習目標

ドリル

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

演習: ドリル 01 — final class でインスタンスを作る

問題

Logger クラスを final を付けて定義してください。

Logger のインスタンスを作って、log("started") を呼んでください。

期待される出力:

[LOG] started

メモ

ヒント

この章を AI に聞く

  1. 「ch08 — final クラス / final メソッド」のつまずきやすいポイントを、初学者向けに3つ教えてください

    💬 ChatGPT 📘 Claude ✨ Gemini

  2. 「ch08 — final クラス / final メソッド」について、自分の手で試せる練習問題を3つ出してください (難易度を上げながら)

    💬 ChatGPT 📘 Claude ✨ Gemini

  3. 「ch08 — final クラス / final メソッド」を学んだ後、次に学ぶと良いトピックは何ですか?理由も教えてください

    💬 ChatGPT 📘 Claude ✨ Gemini

🎉 受講お疲れさまでした!

ch08 — final クラス / final メソッド」を読み終えました。
学んだことを誰かに教えると、もっと記憶に残ります。

X で共有 Hatena LINE