익명 클래스

익명 클래스 (Anonymous classes)

단순하고 한 번만 쓰고 버릴 객체가 필요할 때는 익명 클래스가 특히 유용해요. 클래스에 이름을 붙이는 대신 new class로 바로 객체를 만들 수 있죠. 아래 예제는 똑같은 로거 객체를 명시적 클래스로 만든 경우와 익명 클래스로 만든 경우를 나란히 보여 줘요.

<?php

// Using an explicit class
class Logger
{
    public function log($msg)
    {
        echo $msg;
    }
}

$util->setLogger(new Logger());

// Using an anonymous class
$util->setLogger(new class {
    public function log($msg)
    {
        echo $msg;
    }
});

익명 클래스도 일반 클래스처럼 생성자에 인자를 넘길 수 있고, 다른 클래스를 상속하거나 인터페이스를 구현하고, 트레이트를 쓸 수도 있어요.

<?php

class SomeClass {}
interface SomeInterface {}
trait SomeTrait {}

var_dump(new class(10) extends SomeClass implements SomeInterface {
    private $num;

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

    use SomeTrait;
});

위 예제를 실행하면 이런 결과가 나와요.


object(class@anonymous)#1 (1) {
  ["Command line code0x104c5b612":"class@anonymous":private]=>
  int(10)
}

한 가지 주의할 점이 있어요. 다른 클래스 안에 익명 클래스를 중첩한다고 해서 그 바깥 클래스의 private이나 protected 메서드·프로퍼티에 자동으로 접근할 수 있는 건 아니에요. 바깥 클래스의 protected 멤버를 쓰고 싶다면 익명 클래스가 바깥 클래스를 상속하면 되고, 바깥 클래스의 private 프로퍼티를 쓰고 싶다면 그 값을 생성자를 통해서 넘겨받아야 해요.

<?php

class Outer
{
    private $prop = 1;
    protected $prop2 = 2;

    protected function func1()
    {
        return 3;
    }

    public function func2()
    {
        return new class($this->prop) extends Outer {
            private $prop3;

            public function __construct($prop)
            {
                $this->prop3 = $prop;
            }

            public function func3()
            {
                return $this->prop2 + $this->prop3 + $this->func1();
            }
        };
    }
}

echo (new Outer)->func2()->func3();

위 예제를 실행하면 이런 결과가 나와요.


6

같은 익명 클래스 선언으로 만든 객체들은 전부 저 클래스의 인스턴스예요.

<?php
function anonymous_class()
{
    return new class {};
}

if (get_class(anonymous_class()) === get_class(anonymous_class())) {
    echo 'same class';
} else {
    echo 'different class';
}

위 예제를 실행하면 이런 결과가 나와요.


same class

참고: 익명 클래스에는 엔진이 자동으로 이름을 붙여요. 아래 예제에서 그 모습을 확인할 수 있는데, 이 이름은 구현 세부 사항이니 프로그램에서 의존하면 안 돼요.

> 위 예제를 실행하면 이런 비슷한 결과가 나와요. ```php class@anonymous/in/oNi1A0x7f8636ad2021 ``` ## 읽기 전용 익명 클래스 PHP 8.3.0부터는 익명 클래스에 `readonly` 수식어를 붙일 수 있어요. **예제 #1 읽기 전용 익명 클래스 정의하기** ```php prefix . ' ' . $msg; } }); ```