哪位大佬能解释下关于 PHP 闭包转换的问题

194 天前
 revlis7

这里有篇文章 Link 是关于 PHP 的(...)闭包转换语法的,里面有一个例子是通过闭包转换使得外部函数调用私有成员变量:

<?php
class MyClass
{
    public function __construct(private string $value)
    {
    }
}

echo Closure::fromCallable(fn () => $this->value)
            ->call(new MyClass('THIS IS A PRIVATE VALUE'));
// OUTPUTS
// THIS IS A PRIVATE VALUE

然而转换的方法本身就是一个闭包函数,所以我发现其实这里不做转换一样可以得到结果:

<?php
class MyClass
{
    public function __construct(private string $value)
    {
    }
}

echo (fn () => $this->value)->call(new MyClass('THIS IS A PRIVATE VALUE'));
// OUTPUTS
// THIS IS A PRIVATE VALUE

而当你试图真正将一个类方法转换成闭包时,你却会得到一个 Warning:

<?php
class MyClass
{
    public function __construct(private string $value)
    {
    }
}

$classMethod = new class {
    public function method()
    {
        return $this->value;
    }
};

echo Closure::fromCallable([$classMethod, 'method'])->call(new MyClass('THIS IS A PRIVATE VALUE'));
// OUTPUTS
// PHP Warning:  Cannot bind method class@anonymous::method() to object of class MyClass 

关于这个 Warning 我也查到了一些讨论:

https://stackoverflow.com/questions/47165930/php-binding-method-to-another-class

https://bugs.php.net/bug.php?id=73931&edit=3

我理解大概的意思就是为了避免 $this 在闭包转换后变量产生歧义,那既然如此,我觉得他在这里举的这个例子其实就不是很合理,你完全不需要使用闭包转换,还是说我使用的方式不对?

1164 次点击
所在节点    PHP
2 条回复
ssgooglg
194 天前
我觉得直接问 chatgbt 回复的也不错
Rache1
170 天前
使用类实例方法的时候,你 call 传入的第一个参数(即 this )需要是调用类的祖先类才行(类型兼容)。

https://3v4l.org/jM1rt

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1049218

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX