1

我有一个将可调用对象作为参数的方法。可调用的调用带有一些可以按值或按引用获取的参数,它可能返回一个值,按值或按引用,或不返回。在返回一个值的情况下,它必须由方法从闭包中返回,就像原样一样。如果该值是按引用的,则该方法必须按引用返回它,反之亦然。

问题是无法确定该值是否按引用返回。是的,可以检测闭包是否返回任何值;但是当我尝试获取按值返回的闭包返回值的引用时,我会收到以下通知:

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 符号)运算符,这非常糟糕(参见:12)。将闭包的引用保存到变量,然后返回变量不会改变任何东西(AFAIK)。此外,如代码注释中所述,在内部闭包之前添加与号 (&)Example::get()不是解决方案,并且会产生一些副作用(例如,必须将每个闭包定义为通过引用返回以防止通知,太糟糕了,用户不知道)。所以,请不要推荐这些东西!

有什么办法可以阻止通知吗?难道我做错了什么?一般来说,我可以确定该值是按值返回还是按引用返回(即类似的东西is_reference())?有没有其他解决方案来完成它?

4

0 回答 0