import java.util.concurrent.ThreadLocalRandom;

/**
 * Illustration of runtime polymorphism.
 * 
 * @author Drue Coles
 */
public class PetDemo2 {

    public static void main(String[] args) {
        
        // Inheritance expresses an is-a relationship. Wherever a superclass
        // reference is required, a subtype reference is valid. In particular,
        // Dog is assignment compatible with Pet. An upcast is implicit.
        Pet myPet = new Dog("Isaak", 12945); 
        
        if (ThreadLocalRandom.current().nextBoolean()) {
            myPet = new Cat("Muffin"); 
        }   
         
        // The following statement will not compile:
        //
        // myPet.fetchStick();
        //
        // The compiler does not know the runtime type of myPet. It checks the
        // method name against the declared type of the variable.
        
        // Late binding enables runtime polymorphism. The appropriate version of
        // the method will be invoked depending on the runtime type of myPet.
        myPet.speak();
    }
}