늦은 정적 바인딩

늦은 정적 바인딩

■바인딩(binding)

바인딩이란 프로그램에서 사용된 구성 요소의 실제 값 또는 프로퍼티를 결정짓는 행위

ex) 함수를 호출하는 부분에서 실제 함수가 위치한 메모리를 연결하는 것

1. 정적 바인딩(static binding) : 실행 시간 전에 일어나고, 실행 시간에는 변하지 않은 상태로 유지

2. 동적 바인딩(dynamic binding) : 실행시간에 이루어지거나 실행 시간에 변경(늦은 바인딩)

※ PHP에서는 정적과 동적 중간 정도 수준의 늦은 정적 바인딩(LSB)를 제공

■늦은 정적 바인딩(late static binding, LSB)

PHP 5.3.0부터 제공되는 늦은 정적 바인딩은 static 키워드와 함께 범위 지정 연산자(::)를 사용하여 수행

마지막으로 호출한 비전송 호출(non-forwarding call)의 클래스 이름을 저장하여 동작

이때 정적 메소드 호출에서는 범위 지정 연산자(::) 좌측에 명시된 클래스 이름을 저장하고, 비정적 메소드 호출에서는 해당 객체의 클래스 이름을 저장

static::은 정의된 클래스를 컴파일 시간에 결정할 수 없고, 프로그램 실행 시 전달되는 정보로 결정하므로 늦은 바인딩

또한, 정적 메소드 호출에도 사용할 수 있으므로 정적 바인딩이기도 하다.

■정적 메소드 호출에서의 늦은 정적 바인딩

class A { public static function className() { echo __CLASS__; } public static function printClass() { self::className(); } } class B extends A { public static function className() { echo __CLASS__; } } B::printClass(); // A

class A { public static function className() { echo __CLASS__; } public static function printClass() { static::className(); } } class B extends A { public static function className() { echo __CLASS__; } } B::printClass(); // B

■비정적 메소드 호출에서의 늦은 정적 바인딩

class A { private function className() { echo __CLASS__.""; } public function printClass() { $this->className(); static::className(); } } class B extends A { // className() 메소드는 클래스 B로 복사되므로, // className() 메소드의 유효 범위는 여전히 클래스 A임. } class C extends A { private function className() { // 기존의 className() 메소드가 이 메소드로 대체되므로, // className() 메소드의 유효 범위는 이제부터 클래스 C가 됨. } } $b = new B(); $b->printClass(); // A // A $c = new C(); $c->printClass(); // A // Fatal error : Call to private method C::className() from context 'A'

클래스 B가 클래스 A를 상속받지만, 클래스 B에서 className()을 재정의하지 않으므로 className()의 유효범위는 여전히 클래스 A가 되며, $this나 static::은 모두 클래스 A를 가리키게 된다.

클래스 C는 className()을 재정의하기때문에 className()의 유효범위는 클래스 C로 변경된다.

따라서, $this는 여전히 클래스 A를 가리키지만, static::은 클래스 C를 가리키게 된다.

from http://woong971.tistory.com/64 by ccl(A) rewrite - 2021-11-02 12:26:21