2011-10-24 19 views
1

我是否錯過了某些東西,或者做了關閉操作而不能用作類方法?藉此例如:閉包不能用作類方法?

$foo = new stdClass(); 
$foo->bar = function() { 
    echo '@@@'; 
}; 
$foo->bar(); 

似乎給我的一個錯誤「致命錯誤:在/blah/blah.php調用未定義的方法stdClass的::條()上線X」

不該」而不是調用放置在「bar」屬性中的閉包?

回答

3

是的,這確實是正確的。

調用bar的唯一方法是:

$bar = $foo->bar; 
$bar(); 

可悲,但卻是事實。

另外值得一提的,因爲這同樣的效果,有$酒吧裏面調用沒有 $this(除非你把它當作命名爲 $this函數參數)。

編輯:作爲指出的,$this封蓋內的值是在創建時關閉的範圍的相同的值。 這可能意味着$this可能在兩種情況下未定義:當範圍是全局PHP範圍或範圍來自靜態上下文時。然而,這意味着你可以在理論上養活正確的實例:

class Foo { 
    public $prop = 'hi'; 
    function test(){ 
     $this->bar = function(){ 
      echo $this->prop; 
     } 

     $bar = $this->bar; 
     $bar(); 
    } 
} 

$foo = new Foo(); 
$foo->test(); 

而且,似乎與某些類的魔法,就可以實現$this->bar()還有:

class Foo { 
    // ... other stuff from above ... 
    public function __call($name, $args){ 
     $closure = $this->$name; 
     call_user_func_array($closure, $args); // * 
    } 
} 

[*]當心那call_user_func_array非常慢

哦,這僅限於PHP 5.4。在此之前,有一個在封閉沒有$this :)

此外,你可以看到它在行動here

+0

呃。這是否會很快改變? – dqhendricks

+0

讓我檢查...不。 :) – Christian

+0

$ this在閉包中給我一個錯誤,即它在非對象上下文中使用,即使它是在對象內定義的以及在對象內調用的。 – dqhendricks

1

方法和領域是完全分開的;事實上,你甚至可以有相同的名稱的方法和字段:

<?php 
class foo{ 
    function bar() { echo "hello\n"; } 
} 
$object = new foo; 
$object->bar = 1; 
$object->bar(); // echoes "hello" 
?> 

這就解釋了爲什麼你的語法不能創造一個「真正」的方法。

+0

我沒想到它會創建一個「真實」的方法,但我確實希望它能夠讓我調用財產內的關閉。 – dqhendricks

+0

@dqhendricks:那麼調用方法'bar'和調用存儲在字段'bar'中的函數將不會有語法上的區別。所以這將是模糊的,你在做什麼 – newacct

+0

你是正確的。這會造成混亂。這在我的特殊情況下會是一個非常有用的功能,但是我發現了一種不用它就可以實現相同功能的方法。 – dqhendricks