<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">@SuppressWarnings("unused")
public class Demo {
  public static void types() {
    // Let's create a Cat and a Dog, and assign
    // them each into variables of the same type.
    Cat grumpy= new Cat("Grumpy", 5, 0);
    Dog marnie= new Dog("Marnie", 15);

    // Because the type of grumpy is Cat, it is
    // legal to call getPurrs.
    System.out.println(grumpy.getPurrs());

    // The type of marnie is Dog, so it is clearly
    // illegal to call getPurrs.
    System.out.println(marnie.getPurrs());  // ERROR!

    // It's also legal to call Animal and Object
    // methods on both variables.
    System.out.println(grumpy.toString());
    System.out.println(marnie.isOlder(2));

    // It is *not* legal to assign an expression of type
    // Dog into a variable of type Cat, and vice versa.
    marnie= grumpy;  // ERROR!
    grumpy= marnie;  // ERROR!

    // We can also create a variable of type
    // someAnimal.
    Animal someAnimal;

    // It is legal to assign an expression of type Cat or
    // Dog into a variable of type Animal.
    someAnimal= marnie;
    someAnimal= grumpy;

    // It is *not* legal to call getPurrs on someAnimal,
    // no matter what assignment you did above. (The type
    // of someAnimal is Animal, regardless of any
    // assignment!)
    someAnimal.getPurrs();  // ERROR!

    // It is still legal to call Animal and Object methods.
    System.out.println(someAnimal.toString());
    System.out.println(someAnimal.isOlder(5));
  }

  public static void casting() {
    // This variable has type Animal. At run time, it will
    // point to a Cat object.
    Animal someAnimal= new Cat("Grumpy", 5, 0);

    // This is legal at compile time, and it will succeed
    // at run time. (This is a "downward" cast.)
    Cat someCat= (Cat) someAnimal;

    // This is *also* legal at compile time, but it will
    // raise an exception at run time because someAnimal
    // points to a non-Dog. (This is also a "downward"
    // cast.)
    Dog someDog= (Dog) someAnimal;

    // Casting to an unrelated type is *not* legal at
    // compile time. (It is *guaranteed* to fail because
    // someAnimal cannot point to a String!)
    String someString= (String) someAnimal;

    // An "upward" cast to a superclass is always legal
    // and will always succeed at run time. These are all
    // "upward" casts.
    Object someObject= (Object) someAnimal;
    someObject= (Object) someCat;
    someAnimal= (Animal) someDog;

    // In fact, you don't need to write an upward cast
    // explicitly when you're doing an assignment into
    // a variable whose type is a superclass. It happens
    // implicitly.
    someObject= someAnimal;
    someAnimal= someCat;
  }
}
</pre></body></html>