2013-08-28 1 views
3

최근 PHP에서 호출 범위 및 범위 분석 연산자 (: :)에 대해 읽었습니다. 인스턴스 호출과 통계 호출이라는 두 가지 변형이 있습니다.__call, __call PHP의 정적 범위 및 호출 범위

<?php 

class A { 
    public function __call($method, $parameters) { 
     echo "I'm the __call() magic method".PHP_EOL; 
    } 

    public static function __callStatic($method, $parameters) { 
     echo "I'm the __callStatic() magic method".PHP_EOL; 
    } 
} 

class B extends A { 
    public function bar() { 
     A::foo(); 
    } 
} 

class C { 
    public function bar() { 
     A::foo(); 
    } 
} 

A::foo(); 
(new A)->foo(); 

B::bar(); 
(new B)->bar(); 

C::bar(); 
(new C)->bar(); 

실행 (PHP의 5.4.9-4ubuntu2.2)의 결과입니다 : (new C)->bar();에 대한 A__callStatic()을 실행하는 이유

I'm the __callStatic() magic method 
I'm the __call() magic method 
I'm the __callStatic() magic method 
I'm the __call() magic method 
I'm the __callStatic() magic method 
I'm the __callStatic() magic method 

이해하지 않는 folowing listeng을 고려? 인스턴스 호출은 bar() 메서드의 컨텍스트에서 만들어야합니다. 그렇지 않습니까? PHP의 기능입니까?

Addition1 : 나는 마법 방법을 사용하지 않고 명시 적으로 호출 할 경우

또한, 모든 것이 예상대로 작동이에 대한

<?php 

class A { 
    public function foo() { 
     echo "I'm the foo() method of A class".PHP_EOL; 
     echo 'Current class of $this is '.get_class($this).PHP_EOL; 
     echo 'Called class is '.get_called_class().PHP_EOL; 
    } 
} 

class B { 
    public function bar() { 
     A::foo(); 
    } 
} 

(new B)->bar(); 

결과 :에서

I'm the foo() method of A class 
Current class of $this is B 
Called class is B 
+4

'C :: bar(); '가 오류를 던지지 않은 이유에 대해 더 관심이 있습니다. –

+0

왜? 나는 그것이이 경우에 수정한다고 생각한다. – vasayxtx

+0

[아니에요] (http://stackoverflow.com/questions/3754786/calling-non-static-method-with). 그리고 아마도'E_STRICT'를 던졌다. –

답변

3

bar() 방법이 C이고, 사용자가 A::foo(); :

이 방법은 어느 쪽 A의 인스턴스가 생성되지 않으며 CA 연장 않으므로
public function bar() { 
    A::foo(); 
} 

:: 연산자 A::foo() 정적 메소드를 호출하려고 정전기 연산자로 취급되고있다. foo()A에 정의되어 있지 않으므로 __callStatic() 방법으로 떨어지고 있습니다. 당신이 A을 확장하지 않고 비 정적 메서드를 호출 할 경우에는

, 당신은 A의 인스턴스를 생성해야합니다 :

class C { 
    public function bar() { 
     $aInstance = new A(); 
     $aInstance->foo(); 
    } 
} 
+0

:: ::'항상 statical call을 의미하는 것은 아니다. 그것은 호출 범위에 따라 다릅니다. 'B' 클래스와'A :: foo()'메소드의'(new B) -> bar();'실행'bar()'메소드와 인스턴스의 경우'__callStatic()'메소드를 만든다. 호출 범위. – vasayxtx

+0

@vasayxtx 죄송합니다, 내 생각에 나쁜 말씨 인 것 같습니다. 나는 C.bar() 문맥에서'static' 연산자로 사용된다는 것을 의미했습니다. 다시 말씀 드리 자면, 나는 그것을 더 분명하게 할 수 있습니다. – newfurniturey

0

이 경우에 우리가 A 클래스의 인스턴스가 없기 때문이다 . 그래서 new B 우리에게 A->foo의 비 정적 버전에 액세스 할 수 있습니다

class B extends A 

것을 알 수 있습니다.

클래스 CA을 확장하지 않으므로 A의 정적 메서드 만 사용할 수 있습니다.

+0

좋아, 알았다. 적어도 나에게는 충분하지 않았다. – vasayxtx

+0

걱정하지 마십시오. 이 물건들은 까다 롭고 중요한 세부 사항을 간과하지 않도록 약간의주의가 필요합니다. – Mchl

+0

"클래스 C는 A를 확장하지 않으므로 A의 정적 메서드 만 사용할 수 있습니다." 설명서에서 해당 내용을 읽을 수 있습니까? – vasayxtx