【问题标题】:How do I properly set method of derived class as callable for a parent class?如何正确地将派生类的方法设置为父类的可调用方法?
【发布时间】:2021-03-22 06:56:44
【问题描述】:

我正在编写一个带有一些 call_user_func() 的基本类,然后使用我想从所述 call_user_func() 调用的方法来编写派生类。它看起来如下:

class Basic
{
    private $InputHandler = null;

    public function SetNewHandler(callable $NewHandler)
    {
        $this->InputHandler = $NewHandler;
    }

    public function ProcessInput()
    {
        call_user_func(array($this,$this->InputHandler));
    }
}

class Specific extends Basic
{
    public function Handler()
    {
        echo "Handler() is called\n";
    }
}

$spec = new Specific();
$spec->SetNewHandler('Specific\Handler');
$spec->ProcessInput();
unset($spec);

显然它不起作用,因为Specific\Handler 未被识别为有效的可调用对象。 但是实现这一结果的正确方法是什么?父类应该忽略派生类和/或处理程序方法的实现细节。

我使用 php 7.4

【问题讨论】:

  • 添加回调时,将其作为带有真实实例的数组传递:->setNewHandler([$spec, 'Handler']),然后使用:call_user_func($this->InputHandler) 执行它,如果可行。
  • Specific 总是一个类,Handler 总是一个方法?字符串的格式是Class\Handler?
  • @Raskul 是的。是的。不。字符串的格式可以是任意的,只要它按预期工作即可。
  • @MagnusEriksson 我稍后会看看它是否有效,但第一个想法是我非常喜欢(尽可能)callableSetNewHandler() 中输入提示,因为它提供了某种程度的傻瓜- 证明编码。
  • "字符串的格式可以是任意的,只要它按预期工作即可" - 由于您将提示输入为callable,因此字符串必须遵循特定的预定义格式,这不是任意的。

标签: php callback


【解决方案1】:

我只想在基类中创建一个默认处理程序方法:

class Base
{
    public function ProcessInput()
    {
        $this->Handler();
    }

    public function Handler() 
    {
        // Some default code or just leave empty
        echo "Base Handler() is called\n";
    }
}

class Specific extends Base 
{
    public function Handler()
    {
        echo "Specific Handler() is called\n";
    }
}

$spec = new Specific;
$spec->ProcessInput();

这样您就不需要手动绑定要用于每个实例的处理程序(这可能很麻烦)。如果您想要一个新的处理程序,请使用该处理程序创建一个新类。

这是demo

【讨论】:

  • 哇。为什么我没有想到这么优雅的解决方案...谢谢。
【解决方案2】:

如果您使用 call_user_func(array ($this, $this->InputHandler));方法名称应为第二个数组元素。

class Basic
{
    private $InputHandler = null;

    public function SetNewHandler($NewHandler)
    {
        $this->InputHandler = $NewHandler;
    }

    public function ProcessInput()
    {
        call_user_func(array($this,$this->InputHandler));
    }
}

class Specific extends Basic
{
    public function Handler()
    {
        echo "Handler() is called\n";
    }
}

$spec = new Specific();
$spec->SetNewHandler('Handler');
$spec->ProcessInput();

而不是 call_user_func(Array($this, $this->InputHandler));这在这里也有用吗:

$method = $this->InputHandler;
$this->$method();

或者这个:

$this->{$this->InputHandler}();

或者:可调用对象的传递方式与@Magnus Eriksson 在评论中的描述类似。

class Basic
{
    private $InputHandler = null;

    public function SetNewHandler(callable $NewHandler)
    {
        $this->InputHandler = $NewHandler;
    }

    public function ProcessInput()
    {
        call_user_func($this->InputHandler);
                
    }
}

class Specific extends Basic
{
    public function Handler()
    {
        echo "Handler() is called\n";
    }
}

$spec = new Specific();
$spec->SetNewHandler([$spec,'Handler']);
$spec->ProcessInput();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-31
    • 2015-04-04
    • 1970-01-01
    相关资源
    最近更新 更多