简体   繁体   English

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

[英]Class usage pitfalls breaking Liskov Substitution Principle

In a project I worked recently, noticed that some methods that were accepting a class that belongs to a hierarchy , had code similar to following: 在我最近工作的一个项目中,注意到一些接受属于层次结构的类的方法具有类似于以下的代码:

public void Process(Animal animal) {
    if(animal.GetType() == typeof(Dog)) {
        Console.WriteLine("We have a dog");
    }
    else {
        Console.WriteLine("not a dog");
    }
}

Well, that struck me as a blatant violation of LSP , because now if you use a subclass of a dog , either in production code, unit testing mock, or as a part of dependency injection interceptor this code will not work the same way . 好吧,这让我感到公然违反了LSP ,因为现在如果你使用狗的子类 ,无论是在生产代码,单元测试模拟,还是作为依赖注入拦截器的一部分, 这个代码将不会以相同的方式工作 I believe this particular scenario can be fixed easily, by changing condition to: 我相信通过将条件更改为:可以轻松修复此特定方案:

  if (animal is Dog)

That got me thinking though: 这让我想到了:

Are there any other pitfalls to look for that can break LSP in client code? 是否有任何其他缺陷可以破坏客户端代码中的LSP?

UPDATE UPDATE

Just to clarify, I am looking for possible pitfalls in code that uses the class in a hierarchy. 只是为了澄清,我正在寻找在层次结构中使用类的代码中可能存在的缺陷。 I am aware and I am not looking for problems with badly contstructed hierarchies - (eg rectangle - square problem). 我知道,我不是在寻找层次结构严重的问题 - (例如矩形 - 方形问题)。 I am trying to find out what to look for, to make sure that the code will support dynamic mocks, interceptors, decorated classes (eg LoggingDog) the same way as it would handle original class. 我试图找出要查找的内容,以确保代码将支持动态模拟,拦截器,装饰类(例如LoggingDog),就像处理原始类一样。

So far after going through the answers and links I can see that the only pitfall would be to use type of the class directly - that is use GetType() method directly or through some other technology. 通过答案和链接后到目前为止,我可以看到唯一的缺陷是直接使用类的类型 - 直接使用GetType()方法或通过其他技术。 Despite some comments here is and as operators, and even casting to base type will not break LSP in this case, as sub-classes will evaluate the same way the original class would. 尽管这里的一些意见isas运营商,甚至铸造基地型在这种情况下,不会破坏LSP作为子类将评估以同样的方式原班会。

If we ignore for the moment that there are indeed cases where you may need to cast to a specific type, in most cases the problem can be solved by changing the design: 如果我们暂时忽略了您确实需要转换为特定类型的情况,在大多数情况下,可以通过更改设计来解决问题:

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");
    }
}

By using this design, we avoid the need to cast in the code processing the animals: 通过使用这种设计,我们避免了在处理动物的代码中施放:

var animal = ...; // maybe a Dog, maybe not
animal.Process();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM