6

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

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,因为子类的评估方式与原始类的评估方式相同。

4

1 回答 1

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();
于 2013-02-03T14:33:45.200 回答