5

我最近注意到在某些情况下我真正喜欢做的事情(调用 super)是一种反模式。(http://en.wikipedia.org/wiki/Call_super

所以我的问题是:

如何做以下事情(我们大多数人需要的基本事情,为对象添加一些细节)。我只是将一个新元素添加到一个保存在对象 var 中的数组中:

   <?php
   class A {
       // bla bla bla
       public function __construct() {
            $this->_data['newDetail'] = "Ipiicaei";
       }
   }


   class B extends A {
       // bla bla bla
       // Override constructor, I need to add one more detail for this class
       public function __construct() {
            parent::__construct();
            $this->_data['newDetailSubcls'] = "Something";
       }
   }

现在......如果我不调用父类构造函数来添加第一个元素,我有两种可能性:

  1. 在每个子类中添加父类通常正在执行的代码部分,并将其从父类中删除。因此,如果我用 999 个类扩展它,我将在父级中复制 999*行。对我来说听起来很糟糕。

  2. 从父级调用在子级中实现的方法(模板方法模式,他们推荐的)。因此,如果我只需要一个类来添加它,而其余 998 个类的行为与父类完全相同,那么我在每个类中添加一个空函数。这对我来说也听起来很糟糕。

请记住,我的示例很简单(示例应该是这样的),但是父类和/或子类可能会做复杂的事情。

我可以看到在某些情况下调用 super 可能不好的原因。但在这个对我来说似乎还可以。

那么......你会如何接近?忽略调用 super 是一种反模式并像我一样做(或者如果结果证明我的方式不好,习惯做)?或者……如何?

4

1 回答 1

4

使用构造函数是这种反模式如何出现的一个坏例子,因为在 PHP 中就像在大多数支持继承的语言中一样,

如果孩子没有定义构造函数,那么它可以像普通的类方法一样从父类继承......(来自PHP 手册)。

如果在您尝试定义的任何其他 998 个类中故意不包含构造函数,则将调用基本构造函数,因此几乎需要在每个派生类上添加构造函数以避免此功能。这就是为什么不建议在构造函数中添加可能改变受保护字段/属性状态的逻辑或调用可能在派生类中被覆盖的虚拟方法的原因。

但是,反模式实际上表示:

请注意,调用父级是反模式的要求(来自Wikipedia

因此,只要派生类要求调用基类版本的方法,就可以。即使从未调用基方法,派生类也必须正确运行。这将避免派生类覆盖虚拟方法但未实现某些特殊要求(可能是由于缺少基类的文档)的情况,此时派生类的行为与系统预期的不同,可能导致系统崩溃或行为异常,典型地违反了Liskov 替换原则

在您的特定示例中,此反模式不适用:您正在扩展构造函数,根据定义,当它们将类实例化为有用状态时,它们需要被调用。在大多数情况下,这就是您想要的。

于 2013-06-17T20:02:50.927 回答