返回

将受保护父函数作为回调参数的最佳实践

php

将受保护的父函数作为回调参数传递

问题陈述

在面向对象的编程中,需要将一个受保护的父函数作为回调参数传递给一个函数。但是,由于 protected 修饰符的限制,无法直接访问父类的 protected 成员。

解决方法

有三种方法可以解决这个问题:

  1. 匿名函数

    创建一个匿名函数来引用受保护函数,然后将匿名函数作为回调参数传递。

  2. bindTo() 方法

    对于面向对象的语言,可以使用 bindTo() 方法将一个对象和回调函数绑定在一起,从而允许回调函数访问对象上的 protected 方法。

  3. 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() 函数接受一个数组作为参数,第一个元素是要调用的函数名,其余元素是函数的参数。

常见问题解答

  1. 为什么不能直接传递受保护函数作为回调参数?

    因为 protected 修饰符将成员限制为该类及其子类,这意味着回调函数不能直接访问父类的 protected 成员。

  2. 匿名函数、bindTo() 方法和 call_user_func() 函数有什么区别?

    匿名函数创建了一个新的函数,而 bindTo() 方法将一个对象和回调函数绑定在一起,call_user_func() 函数直接调用一个函数。

  3. 什么时候应该使用哪种方法?

    匿名函数适用于一次性使用的情况,而 bindTo() 方法适用于需要多次访问受保护函数的情况,call_user_func() 函数适用于需要直接调用函数的情况。

  4. 是否有其他方法可以解决这个问题?

    还有一种方法是使用 reflection 来访问受保护函数,但这是一种更高级的技术,不建议用于一般的场景。

  5. 有什么最佳实践?

    一般情况下,建议使用匿名函数,因为它是更简单和直接的方法。对于需要多次访问受保护函数的情况,可以考虑使用 bindTo() 方法。