从PHP的父上下文中访问父级的重写方法

cai*_*005 12 php class

我有一个名为ClassA的绘图PHP类,它由许多其他绘图类扩展,例如ClassB.

我需要继承的类来触发它的父类的Draw()方法.但是,在我的特殊情况下,我不想直接调用这样的方法(例如:) parent::Draw().我想要第三个函数(例如parent::InvokeDraw():)从父元素的上下文中调用我的绘图方法.

这里有一些代码来说明:

class ClassA
{
    function Draw()
    {

        /* Drawing code ... */

    }

    function InvokeDraw()
    {
        $this->Draw();
    }
}

class ClassB extends ClassA
{
    function Draw()
    {
        parent::InvokeDraw();

        /* Drawing code ... */

    }
}
Run Code Online (Sandbox Code Playgroud)

我面临的问题是InvokeDraw()不会调用父的Draw()方法,而是调用扩展类'自己的Draw()方法,从而导致无限循环.

虽然问题相当合理,但我很难找到解决方法.如何完成这项任务?

期望的效果

图表

无限循环问题

图表

Ser*_*sky 2

这是使用静态方法

<?php

class ClassA
{
    function Draw()
    {
        echo "DrawA";
        /* Drawing code ... */

    }

    function InvokeDraw()
    {
        self::Draw();
    }
}

class ClassB extends ClassA
{
    function Draw()
    {
        echo "DrawB";
        parent::InvokeDraw();

        /* Drawing code ... */

    }
}

echo "Begin:<br>";

$cb = new ClassB();
$cb->Draw();
Run Code Online (Sandbox Code Playgroud)

请注意,我唯一更改的是InvokeDraw()方法并使其使用self引用类,而不是像它那样引用对象$this

输出:

Begin:
DrawBDrawA
Run Code Online (Sandbox Code Playgroud)

编辑: 为了回答您下面的评论,我将添加一个关于您的代码如何工作以及该代码如何工作的简短描述。

您的代码中会发生什么:

  1. 我们创建B并开始使用它
  2. 我们在类和对象B->Draw()内工作时调用。BB
  3. B->Draw()A::Invoke()从类 A静态调用(这意味着类方法),我们仍在使用B对象。
  4. 静态调用A::Invoke()调用$this->Draw();,并且当我们当前使用B对象时,$this指的是 的实例ClassB
  5. 我们在这里循环。

上面的代码中发生了什么:

  1. 我们创建B并开始使用它
  2. 我们在类和对象B->Draw()内工作时调用。BB
  3. B->Draw()A::Invoke从类 A静态调用(这意味着类方法),但是在您的代码中我们仍然使用Bobject.
  4. 静态A::Invoke()调用self::Draw()基本上与 and 相同,ClassA::Draw()因为它是静态方法,我们不关心当前正在使用什么对象,我们调用 的A方法Draw()
  5. A::Draw()方法根据我们的需要执行。

我将在第二个答案中为代码提供相同的解释,该答案不使用静态调用:

  1. 我们创建B并开始使用它
  2. 我们在类和对象B->Draw()内工作时调用。BB
  3. B->Draw() 创建的实例A
  4. B->Draw()调用A->Invoke()这意味着我们开始使用一个类实例的对象A,而不是B像以前那样。

此时我们完全忘记了BEven 的存在并且只能与A

  1. A->Invoke()调用$this->Draw()这意味着我们正在调用A->Draw(),因为我们已经使用了类的实例A
  2. A->Draw()按我们的预期执行。

从可用性的角度来看,我们可以看到静态方法更好,因为我们可以定义一些静态属性,并且可以在A::Draw()执行时使用它们。如果我们使用非静态方法,那么我们需要在方法的参数中传递我们需要的数据。

我希望这能够清楚地表明这一点。上面的序列没有正确的术语,但它是故意编写的,我认为这样更容易理解流程。

  • `parent::` 不是静态调用。我假设需要非静态调用“draw”方法,所以这可能行不通。 (2认同)