调用被覆盖的父方法

34
在下面的示例代码中,父类Foo中的test()方法被子类Bar中的test()方法覆盖。是否可以从Bar::test()中调用Foo::test()
class Foo 
{
  $text = "world\n";

  protected function test() {
    echo $this->text;
  }
}// class Foo

class Bar extends Foo 
{
  public function test() {
    echo "Hello, ";

    // Cannot use 'parent::test()' because, in this case,
    // Foo::test() requires object data from $this
    parent::test();
  }
}// class Bar extends Foo

$x = new Bar;
$x->test();

1
foo::test() REQUIRE_DISABLED object data from $this 是什么意思? - nickb
@Oli Charlesworth - 我尝试了很多次,但是我无法弄清楚如何正确地做到这一点,这就是为什么我使用pastebin的原因 :) - kiler129
1
在PHP中,您不能重载方法,只能覆盖。请检查顶部的注释部分:http://php.net/manual/en/language.oop5.overloading.php - Mike Purcell
因此,将您需要的数据传递给函数,该函数应将其作为参数接受。 - nickb
3
当你从对象上下文使用parent::method()时,父方法仍然可以访问$this。 - MrTrick
显示剩余3条评论
5个回答

48

使用 parent:: 在方法名之前,例如:

parent::test();

请参阅parent


6

没错 - 子类使用 parent:: 将引用对象并调用对象方法(而不是静态方法)。谢谢帮忙 :) - kiler129

0

只需在 $text 属性上设置可见性级别。

private $text = "world\n";

-1

调用父级方法可能被认为是不良实践或代码异味,并且可能表明编程逻辑可以通过改进的方式得到改善,使得子类不必调用父类。维基百科 提供了一个很好的通用描述。

没有调用父类的实现应该是这样的:

abstract class Foo
{
    $text = "world\n";

    public function test() {
        $this->test_child();
        echo $this->text;
    }

    abstract protected function test_child();
}// class Foo

class Bar extends Foo
{
    protected function test_child() {
        echo "Hello, ";
    }
}// class Bar extends Foo

$x = new Bar;
$x->test();

调用一个可能存在于扩展类中的函数比重载该函数并调用父类更为不好。在你的示例中,我们必须确保子函数存在——你可以在子类中存根该函数,或者使用接口。通常情况下,如果一个父类完全不需要知道它被扩展的子类,那么会更加美好。我建议你最好在子类中创建相同的函数,并从那里调用 parent::function() - Abraham Brookes
“在扩展类中调用一个可能存在或不存在的函数”是什么意思?实际上,如果它是父类中的抽象方法,那么子类必须实现它,否则会得到这样的结果:试图运行时会出现类似FATAL ERROR Class Bar contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Foo::test_child)。没有“可能存在或不存在”的情况。如果声明了它,它就一定存在,否则代码无法运行。它不能被忽略,不是承诺或猜测,而是一个声明。 - Bence Szalai
我会建议你最好在子类中创建相同的函数,并从那里调用parent::function()。但问题在于,你无法强制子类调用父方法。如果在父方法中有任何关键内容,而子类忘记调用它,那可能会导致运行时头痛,甚至难以检测。然而,我的解决方案不让子类决定是否调用父方法,如果子类未能实现所需的方法,则是编译时问题:自动声明并容易修复。 - Bence Szalai
我想这也取决于数据流 - 你想要子函数在父逻辑之前被调用还是之后?这将影响谁来调用谁。 - Abraham Brookes
我觉得不完全是。调用抽象方法可以放在父方法的第一行、最后一行,甚至中间或嵌套在条件、循环等语句中。这将涵盖所述的使用情况,并在灵活性方面提供更多的支持。 - Bence Szalai

-2
根据你在pastebin上的评论,我会说你做不到。
也许如果你有这样的东西呢?
class foo {
    public function foo($instance = null) {
        if ($instance) {
            // Set state, etc.
        }
        else {
            // Regular object creation
        }
}
class foo2 extends foo {
    public function test() {
        echo "Hello, ";
        // New foo instance, using current (foo2) instance in constructor
        $x = new foo($this);
        // Call test() method from foo
        $x->test();
    }
}

为什么不直接从$this传递所需的参数到foo()中呢?(而不是整个东西) - nickb
他可以通过在test()前缀加上parent:: 来引用test的父版本,就像其他帖子中提到的那样。在被踩之前,你可能想考虑删除它。 - Mike Purcell
@jeanreis - 在我的代码中,几乎不可能像上面那样使用技巧,因为对象有时会占用几兆字节的空间(这是一个服务器应用程序,而不是经典的 Web 脚本)。这样做会导致高内存使用率。 - kiler129
关于 parent::test(),我曾经以为这个方法不能被静态调用,因此我的回答是这样的。那只是一个建议,如果不知道具体情况,很难说它是否可行。 - jeanreis
嗯...PHP作为[半]真正面向对象的语言还很年轻 :) - kiler129

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接