Breaking Bad: Liskov’s Substitution Principle (LSP) violation

Recently I was watching a very nice explanation of LSP on Christopher Okhravi’s YouTube channel. After approximately five minutes of watching this video I wanted to know one thing: how can I actually break it?

Because, you know, breaking things when you learn gives you better understanding of how they work. Am I right?

Let’s start with a simple Adder class and a class which will inherit from it:

public class Adder
{
public virtual int Add(int operand1, int operand2)
{
return operand1 + operand2;
}
}
public class AdvancedAdder : Adder
{
}

The AdvancedAdder class does the same that Adder class does for now. It adds two numbers.

Now we need a UnitTest that will check if the Liskov’s Substitution Principle was violated. It’s done by next three classes:

public abstract class AdderUnitTestsBase
{
protected static Adder Adder;
[DataTestMethod]
[DataRow(2, 2, 4)]
[DataRow(-1, 2, 1)]
[DataRow(2, -3, -1)]
[DataRow(0, 0, 0)]
public void Add_ReturnsCorrectResult(
int operand1, int operand2, int result)
{
Assert.AreEqual(result, Adder.Add(operand1, operand2));
}
}
[TestClass]
public class AdderUnitTests : AdderUnitTestsBase
{
[ClassInitialize]
public static void ClassInit(TestContext context)
{
Adder = new Adder();
}
}
[TestClass]
public class AdvancedAdderUnitTests : AdderUnitTestsBase
{
[ClassInitialize]
public static void ClassInit(TestContext context)
{
Adder = new AdvancedAdder();
}
}

We are ready to break it!

Well to be honest I spent a half of an hour trying to figure it out.  

Adding third parameter to make the AdvancedAdder sum three numbers didn’t break LSP. It just added another Add method with a different signature extending the class functionality.

Changing parameters type did not break it either. Again it just added one more method to the class.

public class AdvancedAdder : Adder
{
public int Add(int operand1, int operand2, int operand3)
{
return operand1 + operand2 + operand3;
}
public uint Add(uint operand1, uint operand2)
{
return operand1 + operand2;
}
}

Then I came up with an idea that I HAVE to override Add method to make it to do something absolutely not related to the Adder class. Subtracting for example:

public class AdvancedAdder : Adder
{
public override int Add(int operand1, int operand2)
{
return operand1 - operand2;
}
}

I did it! 

Summary

It’s not that simple to violate Liskov’s Substitute Principle without overriding a method. Can you do it without “override”?

P.S. When I wrote this post two years ago I was confused by LSP. You can probably see it in the code above.

After some consideration, I decided to keep this post as is. Nostalgy, you know 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *