Source of LiskovSubstitutionPrinciple.java


  1: //LiskovSubstitutionPrinciple.java
  2: //Illustrates Liskov's Substitution Principle.

  4: import java.util.ArrayList;
  5: import java.util.List;

  7: class LiskovSubstitutionPrinciple
  8: {
  9:     public static void main(String args[])
 10:     {
 11:         //The ArrayList class implements the List interface.
 12:         //So ArrayList<Number> is a subtype of List<Number>.
 13:         List<Number> numbers = new ArrayList<Number>();

 15:         //Auto-boxing converts the primitive integer and double to the
 16:         //corresponding wrapper objects, since both the Integer and the
 17:         //Double "wrapper classes" are subtypes of the Number class.
 18:         numbers.add(2016);
 19:         numbers.add(3.14);

 21:         System.out.println(numbers.get(0) + " " + numbers.get(1));

 23:         /*
 24:             But ... and this is counterintuitive ... it's illegal to do this

 26:             List<Number> moreNumbers = new ArrayList<Integer>();

 28:             because get and "incompatible types" error, because the
 29:             Substitution Principle does not work with generic types.
 30:             For suppose the above line did compile. Then later on
 31:             we might try to add a double to a List of Number that
 32:             was actually "only" an ArrayList of Integer.
 33:         */

 35:     }

 37:     /*
 38:         It's also illegal to pass a collection of a subtype to a method which
 39:         has a parameter of the supertype, as the following code illustrates:
 40:         class Animal { }
 41:         class Dog extends Animal { }
 42:         public void addAnimal(List<Animal> animals) { }
 43:         public void test()
 44:         {
 45:             List<Dog> dogs = new ArrayList<Dog>();
 46:             addAnimal(dogs); //Causes compile-time error!
 47:         }
 48:     */
 49: }
 50: /*  Output:
 51:     2016 3.14
 52: */

 54: /*
 55:     In Java, S is a subtype of T if S extends or implements T.

 57:     The (Liskov) Substitution Principle
 58:     A variable of a given type may be assigned a value of any subtype, and a
 59:     method with a parameter of a given type may be invoked with an argument
 60:     of any subtype of that type.

 62:     Further explanation ...
 63:     Substitutability is a principle in object-oriented programming that states
 64:     that, in a computer program, if S is a subtype of T, then objects of type
 65:     T may be replaced with objects of type S (i.e., an object of the type T
 66:     may be substituted with its subtype object of the type S) without altering
 67:     any of the desirable properties of that program (correctness, task
 68:     performed, etc.). More formally, the Liskov substitution principle (LSP)
 69:     is a particular definition of a subtyping relation, called (strong)
 70:     behavioral subtyping, that was initially introduced by Barbara Liskov in
 71:     a 1987 conference keynote address entitled Data Abstraction and Hierarchy.
 72:     It is a semantic rather than merely a syntactic relation because it
 73:     intends to guarantee semantic interoperability of types in a hierarchy,
 74:     object types in particular. Barbara Liskov and Jeannette Wing formulated
 75:     the principle succinctly in a 1994 paper as follows:

 77:     Subtype Requirement:
 78:     Let p(x) be a property provable about objects x of type T. Then p(y) should
 79:     be true for objects y of type S where S is a subtype of T.
 80: */