我最近注意到在某些情况下我真正喜欢做的事情(调用超级)是一种反模式。 (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";
}
}
现在......如果我不调用父类构造函数来添加第一个元素,我有两种可能:
在每个子类中添加父级正常执行的代码部分,并将其从父级中删除。因此,如果我用999个类扩展它,我将在父级中复制999 *行。听起来很糟糕。
从父级实现的方法调用子方法(模板方法模式,他们推荐的方法)。因此,如果我只需要一个类来添加它,并且998的其余部分的行为与父类完全相同,则在每个类中添加一个空函数。这听起来也不好。
请记住,我的示例很简单(这就是示例应该如何),但是父类和/或子类可能会做复杂的事情。
我可以看到为什么在某些情况下呼叫超级可能会很糟糕。但在这一点似乎对我好。
那么......你会怎样接近?忽略那个调用超级是一个反模式并像我一样做(或者如果事实证明我的方式很糟糕)?或者......怎么样?
答案 0 :(得分:4)
使用构造函数是这种反模式如何出现的一个不好的例子,因为在PHP中大多数语言都支持继承,
如果孩子没有定义构造函数,那么它可以像普通类方法一样从父类继承...(来自PHP manual)。
如果在你试图定义的任何其他998类中故意不包含构造函数,那么将调用基础构造函数,这使得在每个派生类上添加构造函数非常需要避免此功能。这就是为什么不建议在构造函数中添加逻辑,这可能会改变受保护字段/属性的状态或调用可能在派生类中重写的虚方法。
然而,反模式实际上表达了:
请注意,调用父的要求是反模式(来自Wikipedia)
因此,只要不要求派生类执行此操作,就可以调用方法的基类版本。即使从不调用基本方法,派生类也必须正确运行。这将避免派生类重写虚拟方法但未实现某些特殊要求(可能是因为缺少基类文档)的情况,此时派生类的行为与系统不一致,可能导致系统崩溃或意外行为,典型违反Liskov substitution principle。
在您的特定示例中,此反模式不适用:您正在扩展构造函数,根据定义,它们需要在将类实例化为有用状态时被调用。在大多数情况下,这就是你想要的。