Design Pattern: Liskov’s Substitution Principle (LSP)

image_pdfimage_print

As a java developper, I’ve never heard of the LSP pattern. It was only when I read some stuff about C++ that I encountered this pattern. It’s very strange because this pattern is sometimes seen as one of the 5 principles of object-oriented programming.

 

This principle was first introduced by Barbara Liskov in 1987 and formulated in 1994 as:

“Let q(x) be a property provable about objects x of type T. Then q(y) should be provable for objects y of type S,where S is a subtype of T.

In other words:

  • if a class B is a subclass of a class A,
  • if A has a method f(),
  • if b is an instance of B and a an instance of A,
  •  then in all the parts of the code using “a.f()” should be able to use” b.f()” without modifying the behavior of the code

 

Let’s have a look of an example of inheritance that doesn’t respect the LSP:

public class MyOrderedCollection {
	protected List<Integer> list = new ArrayList<>();

	public void addElement(Integer i) {
		list.add(i);
	}

	public Integer getElement(Integer index) {
		return list.get(index);
	}
}

public class MyOrderedAndSortedCollection extends MyOrderedCollection {
	//overriding addElement so that the collection is sorted
	public void addElement(Integer i) {
		super.addElement(i);
		Collections.sort(super.list);
	}
}

public class ExampleLSP1 {

	public static void main(String args[]) {
		MyOrderedCollection collection1 = new MyOrderedCollection();
		MyOrderedCollection collection2 = new MyOrderedAndSortedCollection();
		int a = 8, b = 4;
		collection1.addElement(a);
		collection1.addElement(b);
		collection2.addElement(a);
		collection2.addElement(b);
		getAndPrintSecondElement(collection1);
		getAndPrintSecondElement(collection2);
	}

	public static void getAndPrintSecondElement(MyOrderedCollection collection) {
		System.out.println("The second element is :"
				+ collection.getElement(1));
	}
}

The result of this code is:

The second element is :4
The second element is :8

 

Why is this a problem?

MyOrderedAndSortedCollection is ordered so derivate it from MyOrderedCollection seems a nice idea. But since both classes don’t use the same order it could lead to big problems:

  • MyOrderedCollection use the insertion ordering
  • MyOrderedAndSortedCollection use a natural ordering

Suppose devA writes and uses MyOrderedCollection. Two years after, devB creates MyOrderedAndSortedCollection from MyOrderedCollection because he needs a sorted collection. Since it’s an inheritance, the functions using MyOrderedCollection as parameter can also use MyOrderedAndSortedCollection. But what if some of those functions are using the specific ordering of MyOrderedCollection?
In order to avoid that, devB should look at the full legacy code that uses MyOrderedCollection and modify the legacy code to check if the reference is an instance of MyOrderedAndSortedCollection. It could takes weeks depending on the size/complexity of the legacy code and it migh not be a good idea to modifiy an existing (and working) code.

 

Here is a possible solution that respects LSP:

public interface MyCollection {

	abstract public void addElement(Integer i);

	abstract public Integer getElement(Integer index);
}

public class MyOrderedCollection implements MyCollection {
...
}

public class MyOrderedAndSortedCollection implements MyCollection {
...
}

With this configuration MyOrderedCollection and MyOrderedAndSortedCollection are not alike (even if they share the same interface):

  • A code that uses explicitly MyOrderedCollection uses its ordering and can’t be changed with MyOrderedAndSortedCollection.
  • A code using MyCollection doesn’t care about the ordering so it can use whether MyOrderedCollection or MyOrderedAndSortedCollection.

This pattern can be seen as a strong Behavioral subtyping.

image_pdfimage_print

Leave a Reply

2 Comments on "Design Pattern: Liskov’s Substitution Principle (LSP)"

avatar
Rahul
Guest

Hi Christophe,
I think result of the code should be 4 and 8. And in MyOrderedAndSortedCollection class, there will be a compile time error because in addElement() method the list which we are accessing is declared private in MyOrderedCollection class.

wpDiscuz
Proudly powered by WordPress   Premium Style Theme by www.gopiplus.com