2013-08-28 56 views
3

我最近閱讀了PHP調用範圍和範圍解析運算符(:)。有兩種變體:實例調用和靜態調用。考慮如下因素listeng:__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)的結果是:

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 

我不明白爲什麼(new C)->bar();執行的A__callStatic()?實例調用應該在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();

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

由於該方法既不產生的A一個實例,也沒有C延伸A中,操作者::被視爲靜態的操作員試圖調用一個靜態方法A::foo()。因爲foo()沒有在A上定義,所以它回落到__callStatic()方法。

如果你想它來調用非靜態方法,無需延長A,你必須創建A一個實例:

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

'::'並不總是意味着靜態調用。這取決於調用範圍。對於'(new B) - > bar();''執行'B'類的方法而不是'A :: foo()',並且在這種情況下使用'__callStatic()',因爲它是實例調用範圍。 – vasayxtx

+0

@vasayxtx對不起,我猜這是我的錯誤措辭。我的意思是在C.bar()的上下文中,它被用作'靜態'運算符。讓我重新說一句,希望我能說得更清楚。 – newfurniturey

0

這是因爲在這種情況下,我們沒有A類的實例。 注意

class B extends A 

所以new B讓我們訪問的A->foo非靜態版本。

類別C不擴展A所以只有靜態方法A可用。

+0

好吧,我明白了。這並不明顯,至少對我而言。 – vasayxtx

+0

別擔心。這些東西可能會變得棘手,需要一些注意,以免忽略一些次要但重要的細節。 – Mchl

+0

「C類不擴展A,因此只有A的靜態方法可用。」 我可以在手冊中瞭解它嗎? – vasayxtx