设计模式 - 反模式调用超级 - 避免或保持

时间:2013-06-17 14:44:20

标签: php design-patterns anti-patterns

我最近注意到在某些情况下我真正喜欢做的事情(调用超级)是一种反模式。 (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的其余部分的行为与父类完全相同,则在每个类中添加一个空函数。这听起来也不好。

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

    我可以看到为什么在某些情况下呼叫超级可能会很糟糕。但在这一点似乎对我好。

    那么......你会怎样接近?忽略那个调用超级是一个反模式并像我一样做(或者如果事实证明我的方式很糟糕)?或者......怎么样?

1 个答案:

答案 0 :(得分:4)

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

  

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

如果在你试图定义的任何其他998类中故意不包含构造函数,那么将调用基础构造函数,这使得在每个派生类上添加构造函数非常需要避免此功能。这就是为什么不建议在构造函数中添加逻辑,这可能会改变受保护字段/属性的状态或调用可能在派生类中重写的虚方法。

然而,反模式实际上表达了:

  

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

因此,只要要求派生类执行此操作,就可以调用方法的基类版本。即使从不调用基本方法,派生类也必须正确运行。这将避免派生类重写虚拟方法但未实现某些特殊要求(可能是因为缺少基类文档)的情况,此时派生类的行为与系统不一致,可能导致系统崩溃或意外行为,典型违反Liskov substitution principle

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