我有一个将可调用对象作为参数的方法。可调用的调用带有一些可以按值或按引用获取的参数,它可能返回一个值,按值或按引用,或不返回。在返回一个值的情况下,它必须由方法从闭包中返回,就像原样一样。如果该值是按引用的,则该方法必须按引用返回它,反之亦然。
问题是无法确定该值是否按引用返回。是的,可以检测闭包是否返回任何值;但是当我尝试获取按值返回的闭包返回值的引用时,我会收到以下通知:
PHP Notice: Only variables should be assigned by reference in ... on line xxx
同样,该方法按原样(即动态地)返回闭包的返回值。这就是我试图实现的目标:
class Example
{
protected $data = 15;
// Pay attention to this, returning by-reference
protected function &doOnData(callable $function)
{
return $function($this->data);
}
public function increment(): void
{
// No notices, because the closure is defined to return by-reference
$data = &$this->doOnData(function &(&$data) {
return $data;
});
$data++;
}
public function get()
{
// Notice, why you defined the closure to return by-value?
// Defining the closure to return by-reference fixes the problem
// temporarily (i.e. defining as: function &($data))
return $this->doOnData(function ($data) {
return $data;
});
}
public function printData()
{
echo $this->data;
}
}
$example = new Example();
$example->increment();
$example->printData(); // Prints: 16
$data = $example->get(); // Notice!
echo $data; // Prints: 16
正如您在示例中看到的,仅当您将按值返回的闭包传递给时才会产生通知Example::doOnData()
,并且您无法获取其返回值引用。这种情况下就会生成上面的通知(该不该生成?不知道!)。
一个解决方案可能是使用@(at 符号)运算符,这非常糟糕(参见:1和2)。将闭包的引用保存到变量,然后返回变量不会改变任何东西(AFAIK)。此外,如代码注释中所述,在内部闭包之前添加与号 (&)Example::get()
不是解决方案,并且会产生一些副作用(例如,必须将每个闭包定义为通过引用返回以防止通知,太糟糕了,用户不知道)。所以,请不要推荐这些东西!
有什么办法可以阻止通知吗?难道我做错了什么?一般来说,我可以确定该值是按值返回还是按引用返回(即类似的东西is_reference()
)?有没有其他解决方案来完成它?