//LiskovSubstitutionPrinciple.java
//Illustrates Liskov's Substitution Principle.

import java.util.ArrayList;
import java.util.List;

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

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

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

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

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

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

    }

    /*
        It's also illegal to pass a collection of a subtype to a method which
        has a parameter of the supertype, as the following code illustrates:
        class Animal { }
        class Dog extends Animal { }
        public void addAnimal(List<Animal> animals) { }
        public void test()
        {
            List<Dog> dogs = new ArrayList<Dog>();
            addAnimal(dogs); //Causes compile-time error!
        }
    */
}
/*  Output:
    2016 3.14
*/

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

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

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

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

