PHP警告继承的函数声明不兼容

时间:2013-12-02 15:42:28

标签: php oop

我在debug.log中有一个关于PHP严格标准的奇怪警告。

PHP Strict standards:  Declaration of gb_EntryList::fields() should be compatible with mgr_LinearModelCollection::fields($mKey = NULL) in ... on line 339

到目前为止一直很糟糕,但第339行保留了gb_EntryList

的定义
class gb_EntryList extends mgr_mySQLModel

并且gb_EntryList根本没有定义fields()。它从mgr_mySQLModel

继承了这一点
abstract class mgr_mySQLModel extends mgr_LinearModelCollection implements mgr_mySQLModelUpdateable {
   ...
   function fields($mKey = null) { ... }
}

最初,我忘记将= null放入声明中,该声明产生了关于mgr_mySQLModel的类似消息。但现在这些已经消失了。

代码运行得很好,但是这条消息想告诉我什么?

PHP版本:

PHP 5.4.4-14+deb7u5 (cli) (built: Oct  3 2013 09:24:58)

更新

我在这个问题上挖了一下。有趣的是,下面的代码应该具有相同的结构,但php -d error_reporting=4095 -l

是合适的
abstract class A {
  function foo($sText = ""){
     echo "A.foo($sText)\n";
  }
  abstract function bar();
}
abstract class B extends A {
  function foo($sText = ""){
     echo "B.foo($sText)\n";
  }  
}
class C extends B {
  function bar(){
    echo "C.bar()\n";
  }
}

$c = new C();
$c->foo('in C');

实际的类太大了,无法在这里重现它们。但结构与界面继承性相同。但是,上面的代码似乎没问题。实际情况稍微复杂一些:

abstract class mgr_LinearModelCollection implements IteratorAggregate, Countable, ArrayAccess {
    protected $sItemClass;
    function getIterator() { }      
    function count(){ }
    function offsetExists($offset){ }
    function offsetGet($offset){ }      
    function offsetUnset($offset){ }        
    function offsetSet($offset, $value){ }

    function fields($mKey = null){
        $aDummy = call_user_func(array($this->sItemClass,'dummyArray'),$mKey);
        return array_keys($aDummy);
    }
}
interface mgr_mySQLModelUpdateable {
    static function updateTable(array $aOpts = array());
}
abstract class mgr_mySQLModel extends mgr_LinearModelCollection implements mgr_mySQLModelUpdateable{
    protected $aFieldNames = null;
    function fields($mKey = null){
        if(!is_array($this->aFieldNames)) return false;
        return $this->aFieldNames;
    }
}
class gb_EntryList extends mgr_mySQLModel {
    static function updateTable(array $aOpts = array()){ }
}

当然有更多的函数,{ }充满了代码,但除此之外,这是真正未改变的代码,它产生了所述错误消息。我目前不知道,为什么玩具模型很好,但真正的玩具模型不是。任何提示?

2 个答案:

答案 0 :(得分:1)

此E_STRICT消息警告违反了Liskov substitution principle。这意味着已经在超类中定义的方法需要使用超类中方法的参数进行调用。

这将触发消息:

class Super {
  public function foo($argument) {
    echo $argument;
  }
}

class Child extends Super {

  public function foo() {
    parent::foo('bar');
  }
}

输出:

Strict Standards: Declaration of Child::foo() should be compatible 
with Super::foo($argument) in ... on line 15

答案 1 :(得分:0)

你说在gb_EntryList中没有声明field()的事实是出错的线索。 mgr_mySQLModel是一个ABSTRACT类,如果你查看PHP manual entry for abstract classes,线条就​​是“当从一个抽象类继承时,父类声明中标记为abstract的所有方法都必须由子节点定义”。因此,虽然PHP神奇地想要使用父field()方法,但你也应该在子类中声明它。