You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP能否像Python一样在类对象中存储函数并传参调用?

修复PHP中存储函数引用并调用的无限循环问题

首先,你的代码出现无限循环有两个核心原因:

1. 错误地执行了函数而非传递引用

在_create_couplet函数里,你写的$pairing->function1()是直接执行了function1方法(因为加了括号),而不是把方法本身的引用传给_Mapper。由于你没传参数,function1会返回null(因为$value默认是null,null * 2还是null),所以_Mapper的构造函数其实接收的是null,而不是函数引用。

2. 属性名与方法名冲突导致递归调用

你的_Mapper类里,属性名和方法名都是estimator。当你在estimator方法里写$this->estimator($value)时,PHP会优先把$this->estimator解析为当前的方法,而不是你想访问的属性,这就导致了无限递归调用estimator方法,最终引发无限循环。


修正后的代码

下面是修复后的完整代码,我会标注关键改动:

class Pairings {
    public function function1($value = null) {
        return $value * 2;
    }
    public function function2($value = null) {
        return $value * 4;
    }
}

class _Mapper {
    // 改动1:修改属性名,避免和方法名冲突
    private $estimatorFunc;

    function __construct($estimatorFunc) {
        $this->estimatorFunc = $estimatorFunc;
    }

    function estimator($value) {
        // 改动2:调用存储的回调函数,这里用call_user_func处理类方法回调
        return call_user_func($this->estimatorFunc, $value);
    }
}

function _create_couplet($pairing, $A, $B) {
    if ($A < $B) {
        // 改动3:传递类方法的回调引用,格式为[对象实例, '方法名'],不要加括号!
        return new _Mapper([$pairing, 'function1']);
    } else {
        return new _Mapper([$pairing, 'function2']);
    }
}

// 测试代码
$oldValue = 10;
$A = 10;
$B = 5;

$pairing = new Pairings;
$couplet = _create_couplet($pairing, $A, $B);
$newValue = $couplet->estimator($oldValue);

echo "New value: $newValue"; // 输出:New value: 40

其他可选实现方式:用闭包包裹方法

如果你觉得类方法的数组回调不够直观,也可以用闭包来包裹方法调用,这样代码可读性可能更好:

function _create_couplet($pairing, $A, $B) {
    if ($A < $B) {
        // 用闭包捕获$pairing,直接包裹方法调用
        return new _Mapper(function($value) use ($pairing) {
            return $pairing->function1($value);
        });
    } else {
        return new _Mapper(function($value) use ($pairing) {
            return $pairing->function2($value);
        });
    }
}

// 对应的_Mapper的estimator方法可以简化,因为闭包可以直接调用
class _Mapper {
    private $estimatorFunc;

    function __construct($estimatorFunc) {
        $this->estimatorFunc = $estimatorFunc;
    }

    function estimator($value) {
        // 闭包可以直接像普通函数一样调用
        return $this->estimatorFunc($value);
    }
}

关键知识点总结

  • 传递函数/方法引用时,不要加括号:加括号会立即执行函数并返回结果,而不是传递引用。PHP中类方法的回调格式是[对象实例, '方法名'],普通函数直接传函数名字符串即可。
  • 避免属性名与方法名同名:这会导致PHP解析时的歧义,很容易引发递归或者意外行为。
  • 调用回调的方式:可以用call_user_func()/call_user_func_array()处理所有类型的回调,闭包则可以直接像普通函数一样调用。

内容的提问来源于stack exchange,提问作者Philip Lee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:27:41