阶级使用陷阱打破Liskov替代原则

时间:2013-02-03 04:05:46

标签: c# .net types dependency-injection liskov-substitution-principle

在我最近工作的一个项目中,注意到某些接受属于层次结构的类的方法的代码类似于以下代码:

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()方法或通过其他技术。尽管这里有一些注释isas运算符,甚至在这种情况下转换为基类型也不会破坏LSP,因为子类将以与原始类相同的方式进行评估。

1 个答案:

答案 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();