闭包不能作为类方法工作


Closures don't work as class methods?

我错过了什么还是闭包根本不能作为类方法工作?例如:

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

似乎给了我一个错误的"致命错误:调用未定义的方法stdClass::bar()在/blah/blah.php在行X"

这不应该调用放在"bar"属性中的闭包吗?

是的,这确实是正确的。

调用bar的唯一方法是:

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

悲伤,但却是真实的。

同样值得注意的是,由于同样的效果,在$bar调用中没有$this(除非你将其作为名为$this的函数参数传递)。

Edit: nikic指出,闭包内$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:)

也是,你可以在这里看到它的作用

方法和字段是完全分开的;实际上,您甚至可以拥有同名的方法和字段:

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

这解释了为什么你的语法不能创建一个"真正的"方法。