调用父类方法

5

问题编辑以更好地反映我的需求。


以以下示例为例:

class Base
{
    public $Text = null;

    public function __construct()
    {
        $this->Text = new Base_Text();
    }
}

class Base_Text extends Base
{
    public $Is = null;

    public function __construct()
    {
        $this->Is = new Base_Text_Is();
    }

    public function CammelCase($string)
    {
        return trim(str_replace(' ', '', ucwords($string)));
    }
}

class Base_Text_Is extends Base_Text
{
    public function CammelCase($string)
    {
        return ($string === $this->CammelCase($string)); // doesn't work
    }
}

如何在不静态调用Base_Text类(不使用parent::或Base_Text::)的情况下修复Base_Text_Is :: CammelCase()方法?

我想到的唯一解决方案是创建一个像这样的单例函数:

function Base()
{
    static $instance = null;

    if (is_null($instance) === true)
    {
        $instance = new Base();
    }

    return $instance;
}

并将Base_Text_Is :: CammelCase()方法更改为以下内容:

return ($string === Base()->Text->CammelCase($string));

为了避免创建两个Base类的对象实例,不要这样做:
$base = new Base();
$base->Text->Is->CammelCase('MethodOverloading'); // true

我只是执行以下操作:
Base()->Text->Is->CammelCase('MethodOverloading'); // true

这是一种好的做法吗?还有其他解决方案吗?

我不理解你在Darrell的回答中的最后一条评论。你无法访问Base_Text的非静态属性?你想从哪里调用它们?我认为你应该进一步解释这个问题。 - Felix Kling
@Felix:我试图尽可能简化示例,但有些情况下我无法静态调用父方法,因为它取决于已实例化的属性。 - Alix Axel
2个回答

7
你的问题核心在这里:
如何使Son::B()非静态地调用Dad::A()方法(而不使用parent或Dad)?
答案很简单,它不能。你重写了Dad::A()为Son::A()。现在Son对象仅有自己的A()概念。你必须静态调用父类方法,或者在完全不同的Dad对象实例上调用。
底线是,如果你想调用父类A()方法,那么你为什么要先覆盖它呢?
你的结构也没有任何意义。为什么要让$dad->A()的调用传递给$dad->son->A(),然后再调用$dad->son->B(),从你所问的内容来看,又会再次调用$dad->A()?这是一个无限循环。
你的单例方法似乎没有提供任何实际优势,除了确保你不会实例化多个dad对象外,事实上,你仍然需要实例化一个完全独立的对象来执行应该在类内而不是类外部执行的逻辑。
没有看到实际逻辑和你想要实现的目标,很难知道如何建议避免这种循环依赖。但是,我认为你可能需要分析一下你想要做什么,并重新设计继承的工作方式。
编辑
我认为你的继承过于复杂了。你不应该这样做:
$base = new Base();
$base->Text->Is->CammelCase('MethodOverloading'); // true

如果所有的功能都在子类中,你不应该实例化Base类。应该像这样做:
$text = new Text();
$text->isCamelCase('someString');

您的代码可以大大简化,去除所有循环的父/子实例化,并将特定功能下推到子类中:

class Base
{
    //don't put anything related to child classes here,
    //unless it is going to provide specific functionality
}

class Text extends Base
{
    public function CamelCase($string)
    {
        return trim(str_replace(' ', '', ucwords($string)));
    }

    public function isCamelCase($string)
    {
        return ($string === $this->CamelCase($string));
    }
}

这只是一个假设性的例子,我知道它是一个无限循环。然而,我在现实世界中遇到过这种有用的应用程序,并且我一直使用我在问题中提供的解决方案。我只是想知道是否有更好的替代方案。 - Alix Axel
我更新了问题,提供了一个更加现实的例子,并解决了你所提到的一些问题,例如“实例化完全独立的对象”。希望现在能更清楚了。 - Alix Axel
@zombat:我只是想问一下,在我的最后一次编辑中,您是否仍然认为重新设计继承是一个好主意(如果是,有什么建议?),以及在这种情况下使用Base()单例函数是否是一种不好的做法。 - Alix Axel
是的,你的继承关系肯定需要重新设计。你的父类都“依赖于子类的存在”。这不是继承应该使用的方式。另外,子类扩展和替换其父类的功能。如果一个子类覆盖了一个方法,那么你就在说“从现在开始,这个方法由这个子类完成”。我会对我的答案进行编辑。 - zombat

1

我认为没有办法在不静态调用或使用parent::的情况下从子类中调用父类方法。但我可能误解了问题。创建Son()的实例并不会创建两个对象。Son扩展了Dad,但仍然是一个对象。

如果你要在Son中使用Singleton调用Dad(),那么为什么要从Son继承呢?


我已经更新了我的问题,并提供了一个更加现实的例子,请查看。 - Alix Axel
我还是不理解你对使用 parent:: 的厌恶。 - Darrell Brogdon
这不是厌恶,而是因为如果我使用它,我将无法访问Base_Text的非静态属性。 - Alix Axel

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