闭包不作为类方法工作?

时间:2011-10-24 19:25:20

标签: php closures

我是否遗漏了某些东西或者闭包只是不能用作类方法?以此为例:

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

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

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

2 个答案:

答案 0 :(得分:3)

是的,这确实是正确的。

致电bar的唯一方法是:

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

伤心,但确实如此。

另外值得注意的是,由于同样的效果,$ bar调用内没有$this(除非你把它作为名为$this的函数参数传递。) < / p>

编辑:正如指出的那样,闭包内$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中看到它。

答案 1 :(得分:1)

方法和领域完全分开;事实上,你甚至可以拥有一个同名的方法和领域:

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

这解释了为什么您的语法无法创建“真实”方法。