【问题标题】:Zend_Form and Liskov Substitution PrincipleZend_Form 和 Liskov 替换原则
【发布时间】:2009-05-21 20:09:57
【问题描述】:

我看到的一个非常常见的模式(我选择 Zend 框架,只是因为在这个问题的那一刻我正在处理它),是这样的:

class My_Form extends Zend_Form {
     public function init() {
          $this->addElement();
     }
}

Zend_Form 不是一个抽象类,但完全可以单独使用。这似乎被“推荐”为将您的表单“封装”成一个不错的类的地方。

这是否违反了 Liskov 替换原则? Zend_Form 的每个子类都将具有与基类截然不同的行为。为此使用组合会更好,还是我完全误解了这个原则?

【问题讨论】:

    标签: oop zend-framework liskov-substitution-principle


    【解决方案1】:

    Zend_Form 是为继承而设计的。在使用 Zend_Form 时,每个人都应该记住这一点——实际上它不是必需的 Zend_Form,但可能是它的子类。因此,如果任何程序依赖 Zend_Form 来完全按照它的行为而不是它的子类的行为 - 该程序是错误的。正如 Liskov 原则所说,它不是“使用基类”,而是在滥用它。

    Zend_Form 主要由 Zend 框架使用,我确信它正确使用它。

    我认为对于这样的类,为继承而设计并用作基于某些框架的应用程序的构建块,“行为”的定义应该更加抽象 - 将一些细节留给子类,即使类本身不是抽象的。我想说 Zend_Form 的行为是“渲染 some html 并使用 some 验证规则”。在这个意义上, Zend_Form 的所有子类都以相同的方式表现。 Zend_Form 非抽象只是定义了默认行为,使其更易于使用。

    另外,为了使其更具学术性,我可以从中开设两门课程。一个应该是抽象的——所有形式的基类。另一个空表单,它的行为与 Zend_Form 现在的行为完全相同,并且可以单独使用。所以会是这样的

    // sorry, I don't like PHP so here goes java 
    public abstract class ZendForm{/*implementation here and NO abstract methods*/} 
    public final class DefaultZendForm extends ZendForm{/*nothing here*/}
    

    这将消除对 Liskov 原则的任何混淆,但可能不会为程序增加任何实际价值。

    子类应该与超类有所不同,否则创建子类没有意义。而且您总是可以滥用这种差异并编写一个适用于超类而对子类失败的程序。但这不合理。完全呈现默认(空)表单不是 Zend_Form 合同的一部分。只有属于类契约一部分的行为才是 LSP 的主题。

    【讨论】:

      【解决方案2】:

      Liskov 的替换原则指出,如果程序模块使用 Base 类,则可以将 Base 类的引用替换为 Derived 类,而不会影响程序模块的功能。

      那么 MyForm 与 ZendForm 有什么不同呢?它会改变程序的功能吗?

      另外,检查这两个项目符号(来自Wikipedia article):

      • 先决条件不能在子类中加强。
      • 不能在子类中削弱后置条件。

      也许您会发现 MyForm 与 ZendForm 并没有太大的不同,您可以安全地使用继承。

      【讨论】:

      • 它会改变程序的功能,因为 1) 将呈现不同的 HTML 表单,2) 可能使用不同的验证规则。
      • 子类总是做一些与基类不同的事情,否则就不需要它们。因此,1) 与 LSP 不矛盾。也许 2) 这样做是因为(再次引用 Wikipedia)“此外,该原则暗示不应由子类的方法抛出新的异常,除非这些异常本身是由超类的方法抛出的异常的子类型。”
      • 实用性使得扩展 Zend_Form 更有意义,我不会被学术界过度关注
      猜你喜欢
      • 2014-06-05
      • 2010-12-03
      • 2019-10-29
      • 2016-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多