我最近开始阅读有关 Liskov 替换原则 ( LSP ) 的内容,并且我正在努力完全理解“不能在子类型中加强先决条件”这一限制的含义。在我看来,这种限制与建议应该最小化或完全避免从基类向下转换为派生类的需要的设计原则相冲突。
也就是说,我从一个Animal
类开始,并派生出动物Dog
、Bird
和Human
。LSP 对先决条件的限制显然符合自然,因为没有狗、鸟或人应该比一般动物类别更受限制。Bird.fly()
坚持 LSP,派生类Human.makeTool()
将添加特殊功能,例如Animal
.
基类对每个可能的动物子类型的每个可能的特征都有虚拟方法感觉有点荒谬Animal
,但如果没有,那么我需要向下转换Animal
对其底层子类型的引用以访问这些独特的特征。然而,这种低调的需求通常被认为是糟糕设计的危险信号。Wikipedia 甚至暗示,由于 LSP,向下转换被认为是不好的做法。
那么我错过了什么?
额外的问题:再次考虑上面描述的类层次结构Animals
。显然,如果Animal.setWeight(weight)
只需要一个非负数,这将违反 LSP,但Human.setWeight(weight)
加强了这个前提条件并要求一个小于 1000 的非负数。但是对于 的构造函数呢Human
,它可能看起来像Human(weight, height, gender)
?如果构造函数对重量施加限制,是否会违反 LSP?如果是这样,应该如何重新设计这种层次结构以尊重衍生动物物理特性的明确界限?