在我最近工作的一个项目中,注意到某些接受属于层次结构的类的方法的代码类似于以下代码:
public void Process(Animal animal) {
if(animal.GetType() == typeof(Dog)) {
Console.WriteLine("We have a dog");
}
else {
Console.WriteLine("not a dog");
}
}
嗯,这让我感到公然违反 LSP ,因为现在如果你使用狗的子类,无论是在生产代码,单元测试模拟,还是作为依赖注入拦截器的一部分,此代码将无法以相同的方式工作。我相信通过将条件更改为:
,可以轻松修复此特定方案 if (animal is Dog)
这让我想到了:
是否有任何其他缺陷可以破坏客户端代码中的LSP?
更新
为了澄清,我正在寻找在层次结构中使用该类的代码中可能存在的缺陷。我知道并且我不是在寻找严重受限制的层次结构的问题 - (例如矩形 - 方形问题)。我试图找出要查找的内容,以确保代码将支持动态模拟,拦截器,装饰类(例如LoggingDog),就像处理原始类一样。
在完成答案和链接之后,我可以看到,唯一的缺陷就是直接使用类的类型 - 即直接使用GetType()
方法或通过其他技术。尽管这里有一些注释is
和as
运算符,甚至在这种情况下转换为基类型也不会破坏LSP,因为子类将以与原始类相同的方式进行评估。
答案 0 :(得分:4)
如果我们暂时忽略了您可能需要转换为特定类型的情况,在大多数情况下,可以通过更改设计来解决问题:
public class Animal
{
public virtual void Process()
{
Console.WriteLine("Animal (not a dog)");
}
}
public class Dog : Animal
{
public override void Process()
{
Console.WriteLine("We have a dog");
}
}
通过使用这种设计,我们避免了对处理动物的代码进行投射:
var animal = ...; // maybe a Dog, maybe not
animal.Process();