Class Use Traps Break Lisky Replacement Principle

In a project that I recently worked on, I noticed that some methods that accept a class belonging to a hierarchy had code similar to the 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 seemed like a gross violation of LSP because now if you use a subclass of the dog , either in production code, unit testing, or as part of a dependency injection sniffer, this code will not work in the same way . I believe that this particular scenario can be easily eliminated by changing the condition to:

  if (animal is Dog) 

It made me think:

Are there any other problems that can distort the LSP in client code?

UPDATE

To clarify, I look for possible errors in the code that uses the class in the hierarchy. I know, and I'm not looking for problems with poorly arranged hierarchies - (for example, the rectangle problem is a square). I'm trying to figure out what to look for to make sure that the code will support dynamic layouts, interceptors, decorated classes (like LoggingDog) in the same way as for the original class.

So far, after going through the answers and links, I see that the only mistake will be to use the class type directly - this is the GetType() method directly or through some other technology. Despite some comments here, the is and as operators, and even casting to the base type in this case will not violate the LSP, since subclasses will evaluate the same as the original class.

+6
source share
1 answer

If at the moment we ignore that there really are cases when you may need to use a certain 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"); } } 

Using this construct, we avoid the need to introduce into the animal processing code:

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

All Articles