php代码如下:

class bird{
public function __construct($str){
echo "bird __con <br>".$str;
}
}
$eagle=new bird('fly');
//给类的属性/方法赋值一个 匿名函数之后
$eagle->onWorkerStart = function($str){
var_dump($str);
$chicken=new bird('egg');
$chicken->onMessage = function($buffer){
out_f($buffer); //执行外部定义的方法会不会报错?
};
};
$eagle->onWorkerStart();  //这样会报错
($eagle->onWorkerStart)();  //这样也会报错
function out_f($buffer){
echo "out_f".$buffer;
}

问题一:$eagle->onWorkerStart 如何执行???
问题二:$chicken->onMessage里面执行外部定义的方法out_f($buffer)会不会报错?

回答

问题一

用这种方式构建的匿名 onWorkerStart 实际上会成为一个 Closure 对象, 因此你需要调用 Closure 对象的 call 方法 (此处 PHP 应该是参考了 Javascript)

$eagle->onWorkerStart->call($eagle, 'hello'); // 'hello' 为 onWorkerStart 函数的参数

详见 https://www.php.net/manual/zh/class.closure.php

不过个人并不建议你这么做, 对代码可读性伤害很大. 哪怕在 Bird 类里面分别 public 声明下 onWorkerStartonMessage 也会好很多. 并进一步可以用 phpdoc 标示一下它们的类型为 Closure, 现代IDE 可以识别这个语法并根据对应类型提供语法提示.

class bird{
    
    /**
     * @var \Closure
     */
    public onWorkerStart;
    
    /**
     * @var \Closure
     */
    public onMessage;
    
    /*.....*/
}

当然 PHP 7.4 以上可以直接声明类型:

class bird{
 
    public \Closure onWorkerStart;
    
    public \Closure onMessage;
    
    /*.....*/
}

问题二:
不会, 函数是全局作用域的

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Scroll Up