추상 클래스(abstract class) 내부에 선언된 정적(static) 메서드에서 자식 클래스의 인스턴스를 생성해야 하는 경우가 종종 있습니다. 이럴 때는 self와 함께 new static()을 사용하면 해결할 수 있습니다.
핵심 원리: 후기 정적 바인딩(Late Static Binding)
PHP 5.3부터 도입된 후기 정적 바인딩 덕분에 static> 키워드는 실제 호출된 클래스를 기준으로 동작합니다. 따라서 부모 클래스의 정적 메서드 안에서 new static()을 호출하면, 해당 메서드를 호출한 자식 클래스의 인스턴스가 생성됩니다.
예제 코드
다음은 추상 클래스 Base의 정적 메서드에서 자식 클래스 Child의 인스턴스를 생성하고, 추상 메서드를 실행하는 예제입니다.
<!DOCTYPE html>
<html>
<body>
<?php
abstract class Base {
protected static $fullName = '';
// 자식 클래스에서 반드시 구현해야 하는 추상 메서드
abstract protected function customFunction();
// new static()을 사용해 호출된 클래스의 인스턴스를 생성
public static function get_obj($param1 = null, $param2 = null) {
$obj = new static();
$obj->customFunction();
}
public static function getFullName() {
return static::$fullName;
}
}
class Child extends Base {
protected static $fullName = 'John Doe';
protected function customFunction() {
echo self::getFullName() . "<br>";
echo $this;
}
}
// 자식 클래스에서 정적 메서드 호출
Child::get_obj();
?>
</body>
</html>실행 결과
위 코드를 실행하면 다음과 같은 출력이 나타납니다.
John Doe
코드 설명
abstract class Base: 직접 인스턴스화할 수 없는 추상 클래스로, 추상 메서드customFunction()을 선언하여 자식 클래스에게 구현을 강제합니다.new static():new self()와 달리, 실제로 메서드를 호출한 클래스(여기서는Child)의 인스턴스를 생성합니다. 만약new self()를 사용했다면 부모 클래스인Base는 추상 클래스이므로 오류가 발생합니다.static::$fullName: 역시 후기 정적 바인딩을 활용하여, 자식 클래스에서 재정의한 정적 프로퍼티 값('John Doe')을 반환합니다.
이처럼 new static()과 static::을 적절히 활용하면, 추상 클래스의 정적 팩토리 메서드에서도 호출 대상이 되는 자식 클래스의 인스턴스를 유연하게 생성할 수 있습니다.