将受保护父函数作为回调参数的最佳实践
2024-03-18 07:07:51
将受保护的父函数作为回调参数传递
问题陈述
在面向对象的编程中,需要将一个受保护的父函数作为回调参数传递给一个函数。但是,由于 protected 修饰符的限制,无法直接访问父类的 protected 成员。
解决方法
有三种方法可以解决这个问题:
-
匿名函数
创建一个匿名函数来引用受保护函数,然后将匿名函数作为回调参数传递。
-
bindTo() 方法
对于面向对象的语言,可以使用 bindTo() 方法将一个对象和回调函数绑定在一起,从而允许回调函数访问对象上的 protected 方法。
-
call_user_func() 函数
call_user_func() 函数可以用来调用具有特定参数的函数。对于受保护的父函数,可以使用 [[$this, 'toRouterCallable']] 语法来调用。
具体实现
class ParentClass {
protected function toRouterCallable() {}
}
class ChildClass extends ParentClass {
public static function setup(Router $router, Injector $injector, callable $toRouterCallable): void {
// 使用匿名函数
Routes::setup($router, $injector, function () {
return $this->toRouterCallable();
});
// 使用 bindTo() 方法
Routes::setup($router, $injector, $this->toRouterCallable->bindTo($this));
// 使用 call_user_func() 函数
Routes::setup($router, $injector, call_user_func([$this, 'toRouterCallable']));
}
}
注意事项
- 确保子类中存在要传递的受保护函数。
- bindTo() 方法仅适用于面向对象的语言。
- call_user_func() 函数接受一个数组作为参数,第一个元素是要调用的函数名,其余元素是函数的参数。
常见问题解答
-
为什么不能直接传递受保护函数作为回调参数?
因为 protected 修饰符将成员限制为该类及其子类,这意味着回调函数不能直接访问父类的 protected 成员。
-
匿名函数、bindTo() 方法和 call_user_func() 函数有什么区别?
匿名函数创建了一个新的函数,而 bindTo() 方法将一个对象和回调函数绑定在一起,call_user_func() 函数直接调用一个函数。
-
什么时候应该使用哪种方法?
匿名函数适用于一次性使用的情况,而 bindTo() 方法适用于需要多次访问受保护函数的情况,call_user_func() 函数适用于需要直接调用函数的情况。
-
是否有其他方法可以解决这个问题?
还有一种方法是使用 reflection 来访问受保护函数,但这是一种更高级的技术,不建议用于一般的场景。
-
有什么最佳实践?
一般情况下,建议使用匿名函数,因为它是更简单和直接的方法。对于需要多次访问受保护函数的情况,可以考虑使用 bindTo() 方法。