代码之家  ›  专栏  ›  技术社区  ›  Itay Moav -Malimovka

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

  •  6
  • Itay Moav -Malimovka  · 技术社区  · 14 年前

    我正在使用PHP5.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 回复  |  直到 14 年前
        1
  •  5
  •   Tim Stone    14 年前

    注意,bug报告稍微有点偏离,因为只要您的错误级别为 E_STRICT (或者,最近,无论您的错误级别如何,只要您设置了自定义错误处理程序)。

    PHP的 visibility rules 清楚地证明孩子没有能力看到父母的私人成员,我怀疑这对任何人来说都是那么令人惊讶。如果孩子看不到父母的方法,我不明白他们怎么有义务遵守他们的定义。

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

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

    …这样可以避免在父方法被标记为private时出现错误。既然你总是可以选择不登录 E-严格 不过,这并不会对任何事情产生负面影响,我想这也没什么大不了的。我不明白这是怎么故意的,但我也不是一个php引擎开发人员。

        2
  •  2
  •   TCCV    14 年前

    我认为这里有两种可能性。要么是一个bug,要么php.net/manual上的文档不正确。以下是php手册的三个部分。首先是继承:

    对象继承

    继承是一种公认的 编程原理,php使 在其目标中使用此原则 模型。这一原则将影响 许多类和对象与 彼此。

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

    这对于定义和 抽象功能,并允许 附加条款的实施 类似对象中的功能 无需重新实现所有 共享功能。

    在抽象类上:

    抽象类

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

    从抽象类继承时,父类的 类声明必须由子类定义;此外,这些方法必须 具有相同(或较少限制)可见性的定义。例如,如果 方法定义为protected,函数实现必须定义为 受保护的或公共的,但不是私人的。

    最后,接口

    对象接口

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

    接口是使用interface关键字定义的,与标准类一样, 但是没有任何方法定义它们的内容。

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

    可以这么说:文档中没有提到私有方法的继承。如果父方法签名和子方法签名之间存在关系,则不会对其进行记录,错误报告应至少向某人显示文档需要更新(如果决定执行此行为是故意的)。如果不应该有关系的话,那是个真正的错误。

    这是我的看法…

        3
  •  1
  •   Tim Cooper    13 年前

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

        4
  •  0
  •   Hendrik Brummermann    14 年前

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

        5
  •  0
  •   Jari    14 年前

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

    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
        }
    }
    

    在派生类实例上调用dothings方法将执行父类特定的处理,但由于可能重写私有方法,因此仍然可以利用非最终父类customstuff方法提供的扩展点。

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