【问题标题】:Overriding static methods in PHP覆盖 PHP 中的静态方法
【发布时间】:2012-11-01 09:40:03
【问题描述】:

我有一个如下所示的抽象页面类:

abstract class Page {
    public static function display() {
        self::displayHeader();
        self::displayContent();
        self::displayFooter();
    }

    public static function displayContent() {
        print "<p>some content</p>";
    }

    public static function displayHeader() {
        include_once(kContent . "HeaderContent.class.php");
        HeaderContent::display();
    }

    public static function displayFooter() {
        include_once(kContent . "FooterContent.class.php");
        FooterContent::display();
    }
};

我想继承它的子类,并且只覆盖 displayContent 方法,因此页眉和页脚会自动显示,但仍然可以选择覆盖 display 方法,例如 .js 文件。

现在我有另一个类,看起来像这样:

class FooPage extends Page {
    public static function displayContent() {
        print "<p>Foo page</p>";    
};

现在,它不再调用 FooPage 的 displayContent 方法,而是调用超类中的那个。

为什么?我能做什么?

编辑

我正在运行 PHP 5.2.17

【问题讨论】:

  • 使用static 而不是self
  • 不是重复的,对我没用。
  • 为什么display() 方法是静态的?不要这样做,如果你已经有一个对象。然后继承适用于$this
  • 那么你不会得到继承作为回报。 :) 由于静态绑定,B::foo() 将传递给A:foo(),它看起来就像是直接调用了A::foo()。你真的无能为力。

标签: php static overriding


【解决方案1】:

Ilija,PHP Late Static Binding”,这就是为什么您可能会遇到 FooPage::displayContent 未被调用的问题。如果您运行的是 PHP 5.2,那么没有什么可做的(some hacks using debug_backtrace() 除外,老实说我不建议这种情况使用)。

现在,真正引起我注意的是您的方法都是静态的;是否有一个原因?为什么它们不是实例方法?我希望是这样的:

include_once(kContent . "HeaderContent.class.php");
include_once(kContent . "HeaderContent.class.php");

abstract class Page 
{
    protected $header;
    protected $footer;

    public function __construct()
    {
        $this->header = new HeaderContent();
        $this->footer = new FooterContent();
    }

    public function display() 
    {
        $this->displayHeader();
        $this->displayContent();
        $this->displayFooter();
    }

    public function displayContent() 
    {
        print "<p>some content</p>";
    }

    public function displayHeader() 
    {
        $this->header->display();
    }

    public function displayFooter() 
    {
        $this->footer->display();
    }
};

class FooPage extends Page 
{
    public function displayContent() 
    {
        print "<p>Foo page</p>";
    }
}

然后在你看来,你会写这样的东西:

$page = new FooPage();
$page->display();

需要考虑的一些事项:

  • 在生成视图内容时通常最好不要使用打印/回显。而是尝试创建字符串并将打印/回显作为最后一步。这使得以后编写测试更容易。

例子:

public function display() 
{
    return 
           $this->displayHeader() . 
           $this->displayContent() . 
           $this->displayFooter();
}

public function displayContent() 
{
    return "<p>some content</p>";
}

public function displayHeader() 
{
    return $this->header->display();
}
....
$page = new FooPage();
echo $page->display();
  • 如果随着应用程序的增长需要这样做,可以将页眉和页脚作为 Page 构造函数参数传递。只要它们是能够理解 display() 消息的对象(即polymorphic),一切都应该没问题。

HTH

【讨论】:

  • 非常感谢您的回答!好的,它适用于非静态方法。我打印出来的内容如下: ob_start(); $this->output = ob_get_contents(); ob_get_clean();是不是太脏了?
  • 这是我的意思,所以我可以通过关闭 php 标签、插入我的 html 代码并再次打开 php 标签来打印内容。所以我得到语法高亮。
  • 嗯,这主要取决于品味和每个人对“优雅”编码的看法。我更喜欢离开 ob_start();机制的时候,它是唯一的选择。从我的 POV 返回一个字符串是一种更优雅的方法,但代价是失去了语法高亮。与许多其他事情一样,编程总是需要权衡取舍,您应该选择最适合您需求的事情。但是,如果您使用 ob_start() 方法,我建议创建一个“输出抓取器”对象,将其封装在一个方法中,这样您就不会重复 ob_* 过程 N 次。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-21
  • 2010-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多