日期:2014-05-18  浏览次数:20865 次

【关于里氏替换原则】在同一个继承体系中的对象应该有共同的行为特征,这句话该怎么理解啊?
什么是对象的行为,是不是对象的方法就是对象的行为啊!

------解决方案--------------------
基本上可以这样理解。不过原则其实也不能硬套。例如“鸵鸟确实是鸟——只是它的翅膀退化了”。所以我们要看看我们到底是不是要暂时在我们的系统中不考虑鸵鸟,或者改变鸟的定义(例如在鸟的高层次测试中直接先去判断某个分支/接口的特例)。

有一个“很有名地”错误地使用这个原则的例子。它首先写了一个关于矩形的测试用例,“长20乘以宽10则面积等于200”。然后它让一个正方形继承自矩形,并且举例说正方形的长宽相等,因此面积要么等于400要么等于100,就是不会等于200,所以测试用例失败了。于是它僵化地套用这个“原则”,得出了“正方形不能从矩形继承”的结论!

实际上,这种推论是站不住脚的。因为它自始至终都没有给我们展示正方形是如何用到矩形测试用例里的例子,它只是胡乱地写了“如果正方形的边长10(或者20),断言——面积应该等于200”这种想当然的错误的测试用例。可见测试用例入户瞎写,即使是大师也会犯下低级的错误,而且是在号称“全美震撼大奖”的著作中出现低级错。

这种测试用例是错误的。因为对对象的new实例化方法是不能继承的,因此你不可能写出一个new一个矩形对象的代码,它同时得到的又是一个正方形。我们只能相反地说new一个正方形对象的代码,它同时得到的是一个矩形,而已。

所谓“把子类对象带入父类的测试用例中去检验”,是指类似这样的测试用例:“假设已知一个矩形,一边长为x,另一边长为y,则面积是x*y”。这样一个测试用例完全可以给矩形使用。但是假设测试用例中有new一个父类对象的代码,这个测试用例就不能再给子类使用了!


------解决方案--------------------
我举这个例子,跟你所说的“鸵鸟”的例子非常类似。虽然你没有说,但是你其实跟大师的例子是一样的,是想把我绕进去!

如果我们只是为了纠结于这个原则,其实可以找到很多“狡猾的”例子。然而此时我们更主要的原则是“自然”,是以普通人——不懂软件编程的聪明人——能够读懂为原则,而不是单纯以编程设计理论为原则。我们如果花较少的力气对测试用例做少许修改,例如我们在矩形那里设置一个“是否两边可以不相等”的bool属性,那么就通过了。此时是否在滥用继承呢?

还是离开理论,看看我们的对象类型图是否直观易读。以这种“判断”为指引。而不是理论。