update : 2015.11.03
php.shukuma.com

검색:
 
 
늦은 정적 바인딩

늦은 정적 바인딩

PHP 5.3.0 부터, 늦은 정적 바인딩이라는 기능을 구현했습니다. 정적 상속 컨텍스트내에서 호출된 클래스를 참조하는데 사용할 수 있습니다.

자세히 말하자면, 늦은 정적 바인딩은 마지막 "비전달 호출(non-forwarding call)" 내의 클래스명을 저장하여 동작합니다. 정적 메서드 콜의 경우에는, 명명된 클래스명 입니다(대부분 :: 연산자 좌측에 붙습니다); 비정적 메서드 콜의 경우에는, 객체의 클래스명 입니다. "전달 호출(forwarding call)" 은 self::, parent::, static::, 또는 클래스 계층구조에서, forward_static_call() 에 의한 정적인 호출 방법입니다. get_called_class() 함수로 호출 클래스의 이름을 가져올수 있으며, static:: 은 해당 클래스의 스코프입니다.

이 기능은 내부적인 동작을 고려하여 "늦은 정적 바인딩" 이라고 이름지어 졌습니다. "늦은 바인딩" 은 static:: 이 메서드가 정의된 클래스를 결정할수 없으며, 실행시 정보에 의해 정해지는 사실로부터 유래합니다. 이 것은 또한 정적 메서드 호출(그렇게 제한한것은 아니지만) 로 사용할수 있으므로 "정적 바인딩" 이라고 부를수 있습니다.

self:: 제약사항

현재 클래스에 대한 정적레퍼런스인 self::__CLASS__ 는 사용하는 함수가 어디에 정의되었느냐에 따라 결정됩니다.

Example #1 self:: 사용법

<?php
class {
    public static function 
who() {
        echo 
__CLASS__;
    }
    public static function 
test() {
        
self::who();
    }
}

class 
extends {
    public static function 
who() {
        echo 
__CLASS__;
    }
}

B::test();
?>

위 예제의 출력:

A

늦은 정적 바인딩의 사용법

늦은 정적바인딩은 위의 제한을 해결하기 위해 실행시에 최초로 호출된 클래스에 대해 참조하도록 키워드를 도입했습니다. 다시말하면, 키워드는 앞의 예제에서 test() 함수로부터 B를 참조 할수 있도록 합니다. 새로운 키워드 대신에 static 키워드를 사용하기로 하였습니다.

Example #2 static:: 간단한 사용법

<?php
class {
    public static function 
who() {
        echo 
__CLASS__;
    }
    public static function 
test() {
        static::
who(); // 늦은 정적 바인딩
    
}
}

class 
extends {
    public static function 
who() {
        echo 
__CLASS__;
    }
}

B::test();
?>

위 예제의 출력:

B

Note:

비정적 컨텍스트에서는, 호출된 클래스는 오브젝트의 클래스와 동일합니다. $this-> 는 동일한 스코프내의 private 메서드를 호출하려고 하기 때문에, static:: 를 사용하는것은 다른결과를 얻게 됩니다. 또다른 다른점은 static:: 은 정적 속성만을 참조할수 있다는 것입니다.

Example #3 static:: 비정적 컨텍스트에서의 사용법

<?php
class {
    private function 
foo() {
        echo 
"success!\n";
    }
    public function 
test() {
        
$this->foo();
        static::
foo();
    }
}

class 
extends {
   
/* foo() 는 B로 복사됩니다, 스코프가 여전히 A에 있는 이유로 호출은 성공합니다. */
}

class 
extends {
    private function 
foo() {
        
/* 본래 메서드가 대치됩니다. 스코프는 C 가 됩니다. */
    
}
}

$b = new B();
$b->test();
$c = new C();
$c->test();   //fails
?>

위 예제의 출력:

success!
success!
success!


Fatal error:  Call to private method C::foo() from context 'A' in /tmp/test.php on line 9

Note:

늦은 정적 바인딩의 결정은 정적호출이 대체없이 분석될때까지 이뤄집니다. 반면에, parent:: 또는 self:: 키워드를 사용하는 정적호출은 호출정보가 전달 됩니다.

Example #4 전달(Forwarding)과 비전달(non-forwarding) 호출

<?php
class {
    public static function 
foo() {
        static::
who();
    }

    public static function 
who() {
        echo 
__CLASS__."\n";
    }
}

class 
extends {
    public static function 
test() {
        
A::foo();
        
parent::foo();
        
self::foo();
    }

    public static function 
who() {
        echo 
__CLASS__."\n";
    }
}
class 
extends {
    public static function 
who() {
        echo 
__CLASS__."\n";
    }
}

C::test();
?>

위 예제의 출력:

A
C
C