2009-05-21 30 views
2

一个很常见的模式我看到(我捡上Zend框架,只是因为我与它在这个问题的处理时刻),是这样的:Zend_Form和里氏替换原则

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

Zend_Form不是一个抽象类,但它本身是完全可用的。这似乎是“推荐”的地方,将你的表格“封装”成一个好班级。

这是违反Liskov替代原则吗? Zend_Form的每个子类都会具有与基类不同的行为。这样做会更好吗?还是我完全误解了这个原则?

回答

0

Zend_Form是为继承而设计的。在使用Zend_Form的时候,每个人都应该记住这一点 - 实际上,Zend_Form不是必须的,但可能是它的子类。所以,如果任何程序依赖于Zend_Form的行为,而不是它的子类可以行为 - 程序是错误的。正如Liskov原理所说,它不是“使用基类”,而是滥用它。

Zend_Form中被Zend框架,主要用于和我敢肯定,它正确地使用它。

我认为对于这样的类来说,为继承而设计,并且基于某些框架用作构建应用程序块,“行为”的定义应该更加抽象 - 留下一些细节到子类,即使类本身不是抽象的。我要说的是Zend_Form的行为是“渲染一些 HTML和使用验证的一些规则”。从这个意义上说,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*/} 

这将消除约里氏原理任何混乱,但ptobably不会真正的价值添加到程序。

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

0

Liskov的替代原则指出,如果一个程序模块正在使用一个Base类,那么对Base类的引用可以用Derived类替换而不影响程序模块的功能。

因此,如何从不同的是ZendForm MyForm的?它会改变程序的功能吗?

此外,检查这些2枚子弹(来自Wikipedia article):

  • 前提条件不能在子类中得到加强。
  • 后代在子类中不能被削弱。

也许你会发现,MyForm的不是那么从ZendForm显着不同,你可以放心地使用继承。

+0

它会改变程序的功能1)将呈现不同的HTML表单,2)可以使用不同的验证规则。 – blockhead 2009-05-21 20:44:55