2015-02-07 86 views
3

我在PHP中有以下代碼 5.6.2。它有類Father,Guy extends FatherChild extends Guy。所有這些類有一個靜態方法hi其輸出類的名稱:PHP中的靜態匿名函數的意外範圍

class Father { 
    static function hi() { 
    echo "Father" . PHP_EOL; 
    } 
} 

class Guy extends Father { 

    static function hi() { 
    echo "Guy" . PHP_EOL; 
    } 

    static function test() { 
    self::hi(); 
    static::hi(); 
    parent::hi(); 
    $anon = function() { 
     self::hi(); // shouldn't this call Guy::hi()? 
     static::hi(); 
     parent::hi(); // shouldn't this call Father::hi()? 
    }; 
    $anon(); 
    } 

} 

class Child extends Guy { 
    static function hi() { 
    echo "Child" . PHP_EOL; 
    } 
} 

Child::test(); 

我期望的輸出是:被如預期

Guy 
Child 
Father 
Guy 
Child 
Father 

前三行。但最後三個令人驚訝的是:

Child //shouldn't this call Guy::hi()? 
Child 
Father //shouldn't this call Father::hi()? 

如此看來,匿名函數$anonChild範圍。但是它不應該和它被調用的方法有相同的範圍(即Guy)?


編輯1:此外,不會 the specification需要這個工作,如我所料:

一個實例或靜態方法中定義的匿名函數有其範圍設置爲類是定義在其中。否則,匿名函數是不可見的。


編輯2:需要注意的是,當我從 Guy::test()刪除 static修改並調用它像 (new Child)->test();輸出符合市場預期。


編輯3:期待一些更奇怪的行爲之後,我覺得這是在PHP確實是個bug -> according bug report

+0

得到致命錯誤:當無級範圍上線
積極的,如果我執行你的代碼 – Freez 2015-02-07 18:44:36

+0

@KarolyHorvath我不希望'不能訪問自己:: ::喜()'要打印但要在另一個類上調用(請參閱編輯) – MinecraftShamrock 2015-02-07 18:46:00

+0

@Freez我使用http://sandbox.onlinephpfunctions.com/使用PHP 5.6.2來測試 – MinecraftShamrock 2015-02-07 18:46:26

回答

0

孩子繼承功能測試(),所以匿名函數的範圍是兒童,這是「它在「中定義的類」。

+0

難道說'Guy :: test()'的情況完全一樣嗎?不是靜態的?在這種情況下,即使被稱爲「兒童」,它仍然會按照「Guy」中的定義進行處理。 – MinecraftShamrock 2015-02-07 22:44:32

+0

如果Guy :: test()不是靜態的,那麼它不是「在實例或靜態方法內部定義的」。但要想清楚所有的細節,這是很難的。 – bobdye 2015-02-07 22:54:56

+0

您可以請分享一個鏈接從php.net手冊或PHP github規範,指定此?只是爲了讓我可以從根本上學習。 – MinecraftShamrock 2015-02-08 09:27:44