Menu
Coddy logo textTech

匿名クラス

CoddyのPHPジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 58/91。

完全なクラスを定義する手間をかけずに、シンプルで使い捨てのオブジェクトが必要になることがあります。匿名クラスを使用すると、必要な場所でその場でオブジェクトを作成できます。これらは、依存性の注入(dependency injection)と組み合わせると特に便利です。

匿名クラスは、new class を使用し、その後にクラス本体を記述することで定義されます:

<?php
$logger = new class {
    public function log(string $message): void {
        echo "Log: $message";
    }
};

$logger->log("Hello!");

出力:

Log: Hello!

匿名クラスは、インターフェースを実装する際に真価を発揮します。これは、テストを行う場合や、一度しか使わないクラスでコードベースを煩雑にすることなく、迅速に実装を行いたい場合に最適です:

<?php
interface Notifier {
    public function send(string $message): string;
}

function notify(Notifier $notifier, string $msg): string {
    return $notifier->send($msg);
}

$result = notify(new class implements Notifier {
    public function send(string $message): string {
        return "Sent: $message";
    }
}, "Test message");

echo $result;

出力:

Sent: Test message

匿名クラスは、他のクラスを継承したり、トレイトを使用したり、コンストラクタ引数を受け取ったりすることもできます。これらはOOP(オブジェクト指向プログラミング)の機能を完全に利用できます。単に別のファイルではなく、インラインで定義されているだけです。完全なクラス定義では過剰だが、オブジェクト指向の振る舞いが必要な場合に使用してください。

challenge icon

チャレンジ

簡単

匿名クラスの威力を実証するデータフォーマッタシステムを構築しましょう。単純な、一度限りの実装のために個別のクラスファイルを作成する代わりに、匿名クラスを使用して、必要な場所で即座に実装を作成します。

コードは2つのファイルに分けて構成します:

  • FormatterInterface.phpformat(string $data): string という単一のメソッドを持つ FormatterInterface というインターフェースを定義します。これにより、すべてのフォーマッタが従うべき規約が確立されます。
  • main.php — インターフェースファイルを読み込み、依存性の注入(Dependency Injection)を使用して任意のフォーマッタを受け入れる DataProcessor クラスを作成します。このクラスは以下の条件を満たす必要があります:
    • コンストラクタで FormatterInterface を受け取ること
    • 注入されたフォーマッタに処理を委譲し、その結果を返す process(string $data) メソッドを持つこと

    2つの入力を受け取ります:フォーマット形式("upper" または "reverse")と、フォーマットする文字列です。

    フォーマット形式に基づいて、FormatterInterface を実装する匿名クラスを作成します:

    • "upper" の場合:format() メソッドはデータを大文字に変換して返す必要があります
    • "reverse" の場合:format() メソッドはデータを反転させて返す必要があります

    作成した匿名クラスを DataProcessor に注入し、入力文字列を指定して process() を呼び出し、その結果を出力してください。

このアプローチは、使い捨てのクラスファイルでコードベースを散らかすことなく、迅速な実装が必要な場合に最適です。匿名クラスはインラインで作成され、必要なインターフェースを実装し、そのインターフェースが期待される場所ならどこにでも渡すことができます。

チートシート

匿名クラスを使用すると、完全なクラスを定義することなく、その場でオブジェクトを作成できます。これらは、new class の後にクラス本体を続けて定義します。

<?php
$logger = new class {
    public function log(string $message): void {
        echo "Log: $message";
    }
};

$logger->log("Hello!");

匿名クラスはインターフェースを実装できるため、依存性の注入やテストに役立ちます。

<?php
interface Notifier {
    public function send(string $message): string;
}

function notify(Notifier $notifier, string $msg): string {
    return $notifier->send($msg);
}

$result = notify(new class implements Notifier {
    public function send(string $message): string {
        return "Sent: $message";
    }
}, "Test message");

匿名クラスはすべてのOOP機能をサポートしています。他のクラスを継承したり、トレイトを使用したり、コンストラクタ引数を受け取ったりすることができます。完全なクラス定義では大げさすぎるが、オブジェクト指向の振る舞いが必要な場合に使用してください。

自分で試してみよう

<?php
require_once 'FormatterInterface.php';

// TODO: 以下の機能を持つ DataProcessor クラスを作成してください:
// - コンストラクタで FormatterInterface を受け取る
// - フォーマッタに処理を委譲する process(string $data) メソッドを持つ

// 入力を読み込む
$formatType = trim(fgets(STDIN));
$inputString = trim(fgets(STDIN));

// TODO: $formatType ("upper" または "reverse") に基づいて、
// FormatterInterface を実装する匿名クラスを作成してください
// - "upper" の場合: format() はデータの英大文字バージョンを返す必要があります
// - "reverse" の場合: format() はデータの反転バージョンを返す必要があります

// TODO: 作成した匿名クラスのフォーマッタを使用して DataProcessor を作成してください
// 入力文字列を指定して process() を呼び出し、結果を出力してください

?>
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン