クラスの応用

継承・インターフェース・抽象クラス・トレイト

書けるようになったクラスを「継承」「抽象化」「インターフェース」「static」「定数」「final」で本格的な設計に育てるトピック。コードの再利用と契約 (interface) を扱う。

このトピックで身につくこと

  • extends で既存クラスを継承し、必要な部分だけ書き換えられる
  • 抽象クラスとインターフェースの違いを説明できる
  • static を使うべき場面 (共有カウンタ / ユーティリティ) を判断できる
  • const でマジックナンバーを排除できる
  • final でクラス設計の意図を表現できる

前提知識の要点

クラスの基礎 (定義・new・プロパティ・メソッド・$this・コンストラクタ・アクセス修飾子) を理解していれば始められる。他のトピックの README を読み返さずに class-advanced を単独で開始できる ように、以下を圧縮しておく。

1. クラス定義・new$this・コンストラクタ

<?php
class User {
    public string $name;

    public function __construct(string $name) {
        $this->name = $name;
    }

    public function greet(): string {
        return "こんにちは、{$this->name}";
    }
}

$u = new User("太郎");
echo $u->greet();
// => こんにちは、太郎
▶ 3v4l で実行

押さえどころは 4 点:

  • class クラス名 { ... } で設計図
  • public string $name; でプロパティ宣言
  • __constructnew した瞬間に呼ばれる
  • メソッド内では自分のプロパティを $this->name で参照

2. アクセス修飾子

class Account {
    public  int $id;       // どこからでも触れる
    private int $balance;  // クラス内からしか触れない
    protected int $secret; // 自分と子クラスから触れる (このトピックで使う)
}
▶ 3v4l で実行

このトピックでは protected が継承時に重要になる。「private は子クラスからも見えない」「protected は子クラスから見える」だけ覚えておけばよい。

3. 関数の戻り値の型ヒント

function area(float $r): float {
    return 3.14 * $r * $r;
}
▶ 3v4l で実行

このトピックでは抽象メソッドやインターフェースで「戻り値の型を約束する」場面で出てくる。

ここまで読めれば ch01 から始められる。

chapter 一覧

chapter 内容 学習目標
ch01-inheritance/ 継承 (extends) 親クラスのプロパティ/メソッドを子で再利用できる
ch02-override/ メソッドのオーバーライド 子クラスで親のメソッドを上書きできる
ch03-parent-call/ parent:: 呼び出し 子から親のメソッド/コンストラクタを呼べる
ch04-abstract/ 抽象クラス (abstract) 共通部分を抽象化し、子に実装を強制できる
ch05-interface/ インターフェース (interface / implements) 「どんなメソッドを持つか」だけを契約として宣言できる
ch06-static/ static プロパティ/メソッド インスタンス化せずに使える共有領域を扱える
ch07-const/ クラス定数 (const) 変わらない値をクラスに紐づけられる
ch08-final/ final クラス/メソッド 継承・オーバーライドを禁止できる

合計 8 chapter / 7 drill (ch07 は概念説明のみ・drill なし) / 所要 4〜5 時間 程度。継承と抽象化は概念が抽象的なので、ch01〜ch04 は急がず slide.md を 2 回読むくらいで丁度よい。

進め方

  1. 各 chapter の slide.md を読む (3〜5 分)
  2. drill/ 配下の問題を順番に解く (ch07 は読むだけ)
  3. 採点: php scripts/grade.php topics/class-advanced/<chapter>/drill/<drill>/

つまづきポイント

症状 多くの原因
Cannot instantiate abstract class abstract class を直接 new している。継承先のクラスを new する
Class contains abstract methods and must be declared abstract 抽象メソッドを実装し忘れている。interface も同じ
Cannot override final method 親が final で宣言したメソッドを子でオーバーライドしている
parent::Undefined method スペル違い、または親にそのメソッドが存在しない
static メソッドから $this が使えない static 内では $this は存在しない。self::static:: を使う
implements が動かない インターフェースが定義しているメソッドを 1 つでも実装し忘れている (シグネチャ一致も必要)

関連トピック

トピック 関係
class このトピックの前提 (クラスの基本)
exception 継承を使ったカスタム例外を作る
function 抽象メソッド / interface の戻り値型ヒントで再登場

トピックを並列で参照する全体地図は TOPICS_INDEX.md にある。

案件 (dojo_map.tsv) での参照

topic_slug       chapter_dir
class-advanced   topics/class-advanced/ch01-inheritance
class-advanced   topics/class-advanced/ch04-abstract
class-advanced   topics/class-advanced/ch05-interface
...

slug class-advanced で参照可。09-class-advanced / class-advanced どちらの path でもアクセスできる (シンボリックリンク)。

このレッスンの章

  1. ch01 ch01 — 継承 (extends)
  2. ch02 メソッドのオーバーライド
  3. ch03 ch03 — 親メソッドを呼ぶ (parent::)
  4. ch04 ch04 — 抽象クラス (abstract)
  5. ch05 ch05 — インターフェイス (interface / implements)
  6. ch06 ch06 — static プロパティ・メソッド
  7. ch07 ch07 — クラス定数 (const)
  8. ch08 ch08 — final クラス / final メソッド