Software Engineering for Self-Directed Learners »

Can use polymorphism in Java

C++ to Java → Inheritance →

Polymorphism

Java is a strongly-typed language which means the code works with only the object types that it targets.

The following code PetShelter keeps a list of Cat objects and make them speak. The code will not work with any other type, for example, Dog objects.

public class PetShelter {
    private static Cat[] cats = new Cat[]{
            new Cat("Mittens"),
            new Cat("Snowball")};

    public static void main(String[] args) {
        for (Cat c: cats){
            System.out.println(c.speak());
        }
    }
}

Mittens: Meow
Snowball: Meow

The Cat class


This strong-typing can lead to unnecessary verbosity caused by repetitive similar code that do similar things with different object types.

If the PetShelter is to keep both cats and dogs, you'll need two arrays and two loops:

public class PetShelter {
    private static Cat[] cats = new Cat[]{
            new Cat("Mittens"),
            new Cat("Snowball")};
    private static Dog[] dogs = new Dog[]{
            new Dog("Spot")};

    public static void main(String[] args) {
        for (Cat c: cats){
            System.out.println(c.speak());
        }
        for(Dog d: dogs){
            System.out.println(d.speak());
        }
    }
}

Mittens: Meow
Snowball: Meow
Spot: Woof

The Dog class


A better way is to take advantage of polymorphism to write code that targets a superclass so that it works with any subclass objects.

The PetShelter2 uses one data structure to keep both types of animals and one loop to make them speak. The code targets the Animal superclass (assuming Cat and Dog inherits from the Animal class) instead of repeating the code for each animal type.

public class PetShelter2 {
    private static Animal[] animals = new Animal[]{
            new Cat("Mittens"),
            new Cat("Snowball"),
            new Dog("Spot")};

    public static void main(String[] args) {
        for (Animal a: animals){
            System.out.println(a.speak());
        }
    }
}

Mittens: Meow
Snowball: Meow
Spot: Woof

The Animal, Cat, and Dog classes


Explanation: Because Java supports polymorphism, you can store both Cat and Dog objects in an array of Animal objects. Similarly, you can call the speak method on any Animal object (as done in the loop) and yet get different behavior from Cat objects and Dog objects.

Suggestion: try to add an Animal object (e.g., new Animal("Unnamed")) to the animals array and see what happens.

Polymorphic code is better in several ways:

  • It is shorter.
  • It is simpler.
  • It is more flexible (in the above example, the main method will work even if we add more animal types).

Exercises

[Key Exercise] print shape area

The Main class below keeps a list of Circle and Rectangle objects and prints the area (as an int value) of each shape when requested.

Add the missing variables/methods to the code below so that it produces the output given.

public class Main {
    //TODO add your methods here

    public static void main(String[] args) {
        addShape(new Circle(5));
        addShape(new Rectangle(3, 4));
        addShape(new Circle(10));
        printAreas();
        addShape(new Rectangle(4, 4));
        printAreas();
    }
}

78
12
314
78
12
314
16

Circle class and Rectangle class is given below but you'll need to add a parent class Shape.

public class Circle extends Shape {

    private int radius;

    public Circle(int radius) {
        this.radius = radius;
    }

    @Override
    public int area() {
        return (int)(Math.PI * radius * radius);
    }
}
public class Rectangle extends Shape{
    private int height;
    private int width;

    public Rectangle(int height, int width){
        this.height = height;
        this.width = width;
    }

    @Override
    public int area() {
        return height * width;
    }
}

You may use an array of size 100 to store the shapes.

Partial solution


Hint