Previous Lecture Lecture 6 Next Lecture

Lecture 6, Wed 04/17

Inheritance / Polymorphism

Inheritance

Example

// Vehicle.java
public class Vehicle {

    private double maxMPH;
    private String color;

    public Vehicle() {
        System.out.println("Vehicle default constructor");
    }

    public double getMaxMPH() { return maxMPH; }
    public void setMaxMPH(double maxMPH) { this.maxMPH = maxMPH; }
    public String getColor() { return color; }
    public void setColor(String color) { this.color = color; }
}
// Car.java
public class Car extends Vehicle {

    private String make;
    private String model;

    public Car() {
        System.out.println("Car default constructor");
    }

    public String getMake() { return make; }
    public void setMake(String make) { this.make = make; }
    public String getModel() { return model; }
    public void setModel(String model) { this.model = model; } 
}
// Lecture.java

public class Lecture {

    public static void main(String[] args) {
        Car c = new Car();
    }
}
// Output:
Vehicle default constructor
Car default constructor

Default Constructors in Java

    // public Vehicle() {
    //     System.out.println("Vehicle default constructor");
    // }
    public Vehicle(double maxMPH, String color) {
        System.out.println("in Vehicle(double maxMPH, String color)");
        this.maxMPH = maxMPH;
        this.color = color;
    }
public Car() {
        super(100, "black"); // must be first line
        System.out.println("Car default constructor");
    }

    // Add another Car constructor
    public Car(double maxMPH, String color, String make, String model) {
        // Need super() since we are extending from a Base class.
        // super implicitly gets called with Vehicle default constructor.
        super(maxMPH, color); // calls Vehicle(maxMPH, color)
        System.out.println("Car constructor");
        this.make = make;
        this.model = model;
    }
// in main
        Car c = new Car(120, "black", "Pontiac", "GrandAM");

        System.out.println(c.getMaxMPH()); // 120.0
        System.out.println(c.getColor());  // black
        System.out.println(c.getMake());   // Pontiac 
        System.out.println(c.getModel());  // GrandAM

Example with Truck class inheriting from Car

// Truck.java
public class Truck extends Car {

    private double bedVolume;

    public Truck(double maxMPH, String color, String make, String model, double bedVolume) {
        super(maxMPH, color, make, model);
        System.out.println("Truck Constructor");
        this.bedVolume = bedVolume;
    }

    public double getBedVolume() { return bedVolume; }
    public void setBedVolume(double bedVolume) { this.bedVolume = bedVolume; }
}
// in main
Truck t = new Truck(120, "black", "Pontiac", "GrandAM", 400);
System.out.println(t.getMaxMPH()); // 120.0
System.out.println(t.getColor());  // black
System.out.println(t.getMake());   // Pontiac 
System.out.println(t.getModel());  // GrandAM
System.out.println(t.getBedVolume()); // 400.0

Constructor Chaining

Instanceof operator

Example

Car c = new Car(120, "black", "Pontiac", "GrandAM");
if (c instanceof Vehicle)
    System.out.println("instance of Vehicle"); // valid
if (c instanceof Car)
    System.out.println("instance of Car"); // valid
if (c instanceof Truck)
    System.out.println("instance of Truck"); // invalid
if (c instanceof Object)
    System.out.println("instance of Object"); // valid
if (c.getClass().equals(Vehicle.class))
    System.out.println("getClass.equals.Vehicle");
if (c.getClass().equals(Car.class))
    System.out.println("getClass.equals.Car"); // prints this
if (c.getClass().equals(Truck.class))
    System.out.println("getClass.equals.Truck");

Polymorphism (Dynamic Binding)

Object o = new Car(120, "black", "Pontiac", "GrandAM");
Object o2 = new int[100];
Object o3 = new Scanner(System.in);
Car c = new Object(); // illegal!

How come String .equals() works differently if all objects inherit from Object.class?

Example

// in main
Vehicle v = new Vehicle(100, "blue");
System.out.println(v.toString());
// Output
in Vehicle(double maxMPH, String color)
Vehicle@1e81f4dc
// Vehicle.java

    public String toString() {
        System.out.println("In Vehicle.toString()");
        return "maxMPH = " + maxMPH + ", color = " + color;
    }
// in main
Vehicle v = new Vehicle(100, "blue");
System.out.println(v.toString());
// Output
in Vehicle(double maxMPH, String color)
In Vehicle.toString()
maxMPH = 100.0, color = blue

Example

// in Car.java
    public String toString() {
        System.out.println("in Car.toString()");
        return super.toString() + ", make = " + make + ", model = " + model;
    }
// in Truck.java
    public String toString() {
        System.out.println("in Truck.toString()");
        return super.toString() + ", bedVolume = " + bedVolume;
    }
// in main
Car c = new Car(120, "black", "Pontiac", "GrandAM");
System.out.println(c.toString()); // calls Car.toString()

Truck t = new Truck(120, "black", "Pontiac", "GrandAM", 400);
System.out.println(t.toString()); // calls Truck.toString()

Final methods and classes

Example

A polymorphism Example

// in main
vehicleArray[0] = new Vehicle(100, "blue");
vehicleArray[1] = new Car(120, "black", "Pontiac", "GrandAM");
vehicleArray[2] = new Truck(120, "black", "Pontiac", "GrandAM", 400);

for (int i = 0;  i < 3; i++) {
    // call .toString() for each type of object (polymorphism)
    System.out.println(vehicleArray[i].toString());
    System.out.println("---");
}

Memory Slicing

double x = 2.2;
int y = (int) x; // type casted
Object o = new Vehicle(100, "blue");
System.out.println(o.toString());

Casting Objects

Vehicle v1 = (Vehicle) new Object(); // runtime error, ClassCastException
Vehicle v2 = (Vehicle) new Car(120, "black", "Pontiac", "GrandAM"); // OK

Car c = (Car) v2;
System.out.println(c.getModel()); // still OK. Object exists fully on heap

Object o = new Vehicle(100, "blue");
Vehicle v = (Vehicle) o; // OK