PHP致命错误:无法继承抽象函数

时间:2013-07-08 11:35:37

标签: php oop abstract-class

我不明白我做错了什么......

abstract class Css {
    abstract protected function parse($data);
}

abstract class CssElem extends Css {
    abstract protected function parse($data);
}

class Modifier extends CssElem {
    function __construct($data = null) {
        if( $data )
            $this->parse ($data);
    }

    protected function parse($data) {
       // Some code...
    }
}

它给了我:

  

[Mon Jul 8 13:21:10 2013] PHP致命错误:无法继承摘要   函数Css :: parse()(以前在CssElem中声明为abstract)   第21行/home/arthur/NetBeansProjects/capa/CssElem.php [7月8日星期一]   2013年13:21:10] 127.0.0.1:41207 [500]:/ - 不能继承摘要   函数Css :: parse()(以前在CssElem中声明为abstract)   第21行/home/arthur/NetBeansProjects/capa/CssElem.php

第21行是CssElem中的abstract protected function parse($data);

我对Java中的OOP比较熟悉,但根据the doc来看似乎没问题......

4 个答案:

答案 0 :(得分:16)

尝试将中间类更改为:

abstract class CssElem extends Css {
    // abstract protected function parse($data); // <-- take this away
}

另请参阅文档中的this comment

引用评论:

  

扩展抽象类的抽象类可以将降级传递给   它的子类在实现抽象方法时   它的父抽象类。

然而,似乎在下一个PHP version 7.2

中允许这样做
  

现在允许在子类中使用另一个抽象方法覆盖抽象方法。 (https://wiki.php.net/rfc/allow-abstract-function-override

答案 1 :(得分:12)

Patrick Huy的答案肯定是有帮助的。

此错误记录在此处:
https://bugs.php.net/bug.php?id=43200
如前所述,如果您想扩展传统接口,则该错误是相关的。

它可以在http://3v4l.org上复制,表明它自PHP 5.3.9起已修复。

最简单的形式

这可以修复&#34;使用Matteo Tassinari的解决方案,在第二个界面中注释掉foo()的定义。

http://3v4l.org/qo6sG
5.0.0 - 5.3.8:致命错误:不能继承抽象函数A :: foo()
5.3.9 - *:没问题。

interface A {
  function foo();
}

interface B extends A {
  function foo();
}

添加了可选参数

http://3v4l.org/ZXq0O
5.0.0 - 5.3.8:致命错误:不能继承抽象函数A :: foo()
5.3.9 - *:没问题。

interface A {
  function foo();
}

interface B extends A {
  function foo($x = NULL);
}

添加了必需参数

http://3v4l.org/5fPBO
5.0.0 - 5.3.8:致命错误:不能继承抽象函数A :: foo()
5.3.9 - *:致命错误:B :: foo()的声明必须与(A :: foo()

的声明兼容
interface A {
  function foo();
}

interface B extends A {
  function foo($x);
}

(我们并不感到惊讶,这在所有PHP版本中都会中断)

在实施中添加了可选参数:

http://3v4l.org/UvcLA
5.0.0 - *:没问题

/**
 * @legacy
 */
interface A {
    function foo();
}

/**
 * Supersedes legacy interface A
 */
interface B extends A {
    /**
     * @param int|null $x
     *   Optional parameter added in new version.
     */
    # function foo($x = NULL);
}

class C implements B {
    function foo($x = NULL) {}
}

答案 2 :(得分:3)

我最近也遇到过这个问题。对我来说,它有助于从PHP 5.3.8升级到PHP 5.3.28。

我不确切知道改变发生的时间,但是在5.3.28中,可以在抽象类中重新声明接口方法并仍然从它们继承。

答案 3 :(得分:2)

您不需要再次重新声明抽象函数,现在就在实现上声明。

当你在CssElem上扩展Css时,函数解析就会结合在一起。当你实现CssElem时,你也应该实现解析函数。