Tuesday, January 9, 2007

Liskov Substitution Principle in Java

I'm working on some examples that show what is, as I can understand, the meaning of the Liskov Substitution Principle, and how you can deal with it in Java.

The home of the project is http://code.google.com/p/sampleliskov/

A lot of issues are pointed out, particularly about the implementation of equals in a way that respects the principle and the equals contract (transitivity, simmetry, reflexivity) as well.

Another point is a sort of randomized test that shows statistical evidence that two objects are substituble.

You can find on the net a lot of opinions and example of code, that advocates implementation of equals by getClass, or by instanceof.

You can put on google keywords like "some objects are not equals than other" or "equals liskov substitution principle Bloch" to find those opinions.

Essentially: the guys that prefer to implement equals by getClass say that using instanceof violates the equals contract (simmetry and so on...), and the guys that advoacate instanceof says that implementing it with getClass doesn't respect the Liskov Substitution Principle.

The second is true, but I think that the first is not necessarily true, and it's I'm trying to investigate.


Issues about intanceof may happen when you compare a class with its subclass: there can be no transitivity, or, after fixing this, no simmetry.

After this experience I'm confident that it is possible to address this issue in a simple way: when you compare a class with any class that is recognized as a your subclass then you delegate to the subclass the equality check.

This check is also "open" to extentions and so it does not violate another related principle that is called "open closed".

Other parts of the code are related to other issues about lsp and some way to detect lsp violation without using any "design by contract" extension framework.

A simple approach is: use Junit and rewrite the same tests you wrote for the class, for the subclass as well, and if those tests does not succed, then the principle is violated.

Another triky approach I experimented suggests a sort of "randomized" test: generate a random sequance of state for the object of the class, repeat it for the object of the subclass and then check their "equality".

Tonino

P.s.: I want to make clearer something about this "equals" concept, because you can argue, correctly, that "equals" is not the correct term. It rather should be called "equivalent state" or "similar".
In fact two mutable objects should not implement equals as "same state", but as "same object". (from Barbara liskov - Program development in java, pag 94).
I can use, for mutable object, another method, like "similar", according to Liskov .
I'd have to change the code a little bit in order to be more compliant with object orientation.
I'll write a "revised version" of this post.

However: it does not change the mainstream ideas I focused that are:
- the implementation of equals in a way that allows mixed type comparison between type and subtypes,
with "open closed principle" compliancy
- the "randomized" test that shows statistical evidence that two object are substituble.

1 comment:

Tonino Lucca said...

This is an old post, and I think that I should revise it.