这是一个php错误:子类必须使用与父类相同的签名声明私有方法

时间:2010-07-15 18:09:27

标签: php oop inheritance

我正在使用php 5.3,是的,有一个bug open,但有些人认为这不是一个错误,这让我很奇怪。

abstract class A{
   private function bobo(array $in){
     //do something
   }
}

class B extends A{
   private function bobo($shmoo,$shmaa){
     //do something
   }
}

这会引发错误。不应该继承忽略私有方法吗?!

  

'B :: bobo()的声明应该是   与A :: bobo()'

兼容

5 个答案:

答案 0 :(得分:5)

请注意,错误报告略有偏差,因为只要您的错误级别为E_STRICT,PHP就会记录此消息(或者,最近,无论您的错误级别如何,只要您设置了自定义错误处理程序)。

PHP的visibility rules清楚地表明,孩子无法看到其父母的私人成员,我怀疑这对任何人都是如此令人惊讶。如果孩子看不到其父母的方法,我不明白它如何有责任遵守他们的定义。

我个人认为这个错误被标记为虚假而没有任何解释为什么它不是一个真正的缺陷(因为它不明显,我在其中找不到任何提及它文档)有点不对,但是。除此之外,我在zend_compile.c中的第2669条意见应该如下所示:

} else if (child->prototype &&
    (EG(error_reporting) & E_STRICT || EG(user_error_handler))) {

...当父方法被标记为私有时,这将避免错误弹出。鉴于您总是可以选择不记录E_STRICT,但它并没有对任何事情产生负面影响,我认为这并不是什么大问题。我绝对不知道它是如何故意的,但我也不是PHP引擎开发者。

答案 1 :(得分:2)

我认为这里有两种可能性。它是一个错误或PHP.net/manual上的文档是不正确的。以下是PHP手册的三个部分。首先是继承:

  

对象继承

     

继承已经成熟   编程原理,和PHP一起制作   在其目标中使用这一原则   模型。这个原则会影响到   许多类和对象的关系   彼此。

     

例如,当你扩展一个类时,   子类继承了所有的   公共和受保护的方法   父母班。除非班级重写   那些方法,他们会保留他们的   原始功能。

     

这对定义和有用   抽象功能和许可   执行额外的   类似对象中的功能   无需重新实现所有   共享功能。

关于抽象类:

  

类抽象

     

PHP 5引入了抽象类和方法。不允许创建实例   已被定义为抽象的类的包含至少一个的任何类   抽象方法也必须是抽象的。定义为抽象的方法只是声明了   方法的签名他们无法定义实现。

     

从抽象类继承时,所有方法都在父类中标记为抽象   类声明必须由儿童定义;另外,这些方法必须是   使用相同(或限制较少)的可见性定义。例如,如果是摘要   方法定义为protected,函数实现必须定义为   受保护或公开,但不是私人的。

最后,接口

  

对象接口

     

Object interfaces允许您创建指定类必须使用的方法的代码   实现,而不必定义如何处理这些方法。

     

使用interface关键字定义接口,与标准类相同,   但没有任何方法定义其内容。

     

接口中声明的所有方法都必须是公共的,这是接口的本质。

我只想说:文档中没有提到私有方法的继承。如果父方法和子方法签名之间存在关系,则不会记录,并且错误报告至少应该向某人显示文档需要更新(如果决定是否有意这种行为)。如果不存在关系,那么,这是一个真正的错误。

这是我的意见......

答案 2 :(得分:1)

在删除界面时的错误报告中没有错误。 这使得它“更”奇怪的行为,因为界面只是空的。

答案 3 :(得分:0)

我想这是该语言的设计决定。 Java语言开发人员认为这应该是可能的。

答案 4 :(得分:0)

继承应该不会忽略私有方法,例如考虑模板方法模式,您可以在其中覆盖派生类中函数的行为,但父类仍然可以调用该函数

public class Parent {
    public final function doThings() {
        $this->initialize();
        $this->customStuff();
        $this->cleanup();
    }

    private final function initialize() {
        // initialize processing
    }

    private final function cleanup() {
        // cleanup processing
    }

    private function customStuff() {
        // parent specific processing
    }
}

public class Derived extends Parent {
    private function customStuff() {
        parent::customStuff();
        // + derived class specific processing
    }
}

在Derived类实例上调用doThings方法将执行父特定处理,但由于可以覆盖私有方法,因此仍然可以利用非最终父类customStuff方法提供的扩展点。

编辑:PHP方法签名也只包含方法名称,因为您可以定义一个采用零参数的方法,并仍然使用多个参数调用它。然后,函数可以使用func_get_args函数访问参数。