# Lecture 13: Casting and Objects

## Overview

1. Casting
2. Hierarchy and the Object class
3. Extending our Zoo

## Last Time

Polymorphism!

• Instances can identify with with multiple classes:
Animal alice = new Elephant("Alice");
alice instanceof Animal   // returns true
alice instanceof Elephant // also returns true

• Can use this behavior to create collections of different types of Animal:
Animal zoo[] = new Animal[2];
zoo[0] = new Elephant("Alice");
zoo[1] = new Platypus("Bob");


## Today: Going Farther

We have an array of different Animals…

Animal zoo[] = new Animal[2];
zoo[0] = new Elephant("Alice");
zoo[1] = new Platypus("Bob");

• Different Animals do different things
• We saw:
• calling zoo[0].feed() calls Elephant version of feed
• calling zoo[1].feed() calls Platypus version of feed
• What about methods particular to Elephant and Platypus?
• an Elephant can trumpet()
• a Platypus can sting()

## What Happens…

… if we call

zoo[0].trumpet(); // zoo[0] is an Elephant
zoo[1].sting();   // zoo[1] is a Platypus


## We Got an Error!

Zoo.java:23: error: cannot find symbol
zoo[0].trumpet();
^
symbol:   method sting()
location: class Animal
1 error


The reason:

• zoo is declared to be an array of Animals
• trumpet() is not declared for Animal
• (feed() is declared in Animal)
• even though Java knows zoo[0] is an Elephant, the compiler complains because zoo[0] wasn’t declared as an Elephant.
• Java is strongly typed

## An Ethical Dilemma

What is the point of having a Zoo if your Elephants can’t trumpet()?

## Recall casting

• We can convert some primitive data types to others
• Some conversions are automatic:
int n = 10;
double d = n; // java thinks this is okay


## But…

    double d = 10.0;
int n = d;


gives

    error: incompatible types: possible lossy conversion from double to int


## Explicit Casting

We can force Java to do the conversion by casting:

    double d = 10.0;
int n = (int) d; // truncates d (i.e., removes everything after the decimal)


## Casting with class

• We can also cast instances of classes to subclasses
• The following gives an error since sting is not defined for Animal
  Animal alice = new Elephant("Alice");
alice.trumpet();

• The variable alice is treated as a reference to an Animal, not an Elephant
• We can make a new variable referring to the same instance, but treated as a Elephant:
    Elephant aliceToo = (Elephant) alice; // cast alice a ref to Platypus
aliceToo.trumpet(); // this works now!


## In Our Zoo

We can

1. check if Animals are Elephants
2. if so, cast the Animal as an Elephant, then have it trumpet()
	for (int i = 0; i < animals.length; i++) {
animals[i].feed();
if (animals[i] instanceof Elephant) {
Elephant e = (Elephant) animals[i];
e.trumpet();
}


## A Word of Caution

The Java compiler will let you cast as any sub-class of Animal:

	for (int i = 0; i < animals.length; i++) {
animals[i].feed();
if (animals[i] instanceof Platypus) {
Elephant e = (Elephant) animals[i];
e.trumpet();
}
}

• This code compiles
• Only get an error when we run the program
Exception in thread "main" java.lang.ClassCastException: class Platypus cannot be cast to class Elephant (Platypus and Elephant are in unnamed module of loader 'app')
at Zoo.main(Zoo.java:19)

• The error is logical not syntactic

# Hierarchy and the Object class

## Taking Things a Step Farther

• A class can have at most one parent class
• cannot have
  class MyClass extends SomeClass, AnotherClass {...}

• no multiple inheritance
• But the parent class can itself have many sub-classes

## Inheritance Diagrams

How to depict relationship between Shape, Circle, Rectangle, Ellipse, Square, Quadrilateral, Triangle?

## Object: The Mother of all Classes

Every class in Java is automatically a subclass of Object

• every class inherits methods from Object:
• boolean equals(Object obj)
• String toString()

Why is this good?