Polymorphism in Java - A Quiz on things you probably didn't know
Tags: java, polymorphism, tutorial, oop
Published: 2022-01-26 12:29:43


Well if you're reading this, you probably know Java and have worked with a Java Framework. The below post is for all levels of Java 8 developers, anyone looking to improve. I'll try and cover some more advanced concepts of how polymorphism works and some gotchas that exist through some questions and answers!

## Questions
See if you can answer the below questions. They are in increasing order of difficulty. Take your time and answer them. Some will have compilation errors/run time errors. 
Write down your answer on a notepad and check them all at once. The answers and their explanations are in the second section of this post. 

### Level 1
<a name="question-1"></a>
Concepts: Polymorphism
Question: Which lines when commented will the code successfully compile?
```
package com.markbdsouza.polymorphism;

interface Movable{ void move();}
interface Eats{ void eat();}
interface Vertebrae extends Movable, Eats{}
class Dog implements Vertebrae {
    public void move() {
        System.out.println("Dog moves on 4 legs");
    }
    public void eat() {
        System.out.println("Dog eats food");
    }
}
public class Level1 {
    public static void main(String[] args) {
        // which lines when commented will the code successfully compile ?
        Movable a = new Dog(); // line 17
        a.move(); // line 18
        a.eat(); // line 19
        Eats b = new Dog(); // line 20
        b.move();// line 21
        b.eat();// line 22
        Vertebrae c = new Dog(); // line 23
        c.move();// line 24
        c.eat();// line 25
    }
}
```

### Level 2
<a name="question-2"></a>
Concepts: Polymorphism 
Question: What is the output of the below program? 
```
package com.markbdsouza.polymorphism;

interface Movable {
   void move();
}
class Fish implements Movable {
   void move(){System.out.println("swims");}
}
public class Level2 {
    public static void main(String[] args) {
        Movable fish = new Fish();
        fish.move();
    }
}
```

### Level 3
<a name="question-3"></a>
Concepts : Overriding + Polymorphism
Question: Given that FileNotFoundException and EOFException are child exceptions of IOException, will the below code compile?
```
package com.markbdsouza.polymorphism;

import java.io.EOFException;
import java.io.FileNotFoundException;
import java.io.IOException;

class Animal{
    public void move() throws FileNotFoundException { System.out.println("moves in some way");}
}
class Fish extends Animal{
    public void move() throws FileNotFoundException, EOFException {System.out.println("swims");}
}
public class Level3 {
    public static void main(String[] args) throws IOException {
        Animal z = new Fish(); z.move();
    }
}
```

### Level 4
<a name="question-4"></a>
Concept: Polymorphism + Overloading 
Question: What is the output of the below program? 
```
package com.markbdsouza.polymorphism;

class Car {}
class Audi extends Car {}
public class Level4 {
    public void drive(Car car) {
        System.out.println("Using a Car");
    }
    public void drive(Audi audi) {
        System.out.println("Using an Audi");
    }
    public static void main(String[] args) {
        Car car = new Car();
        Audi audi = new Audi();
        Car audiCar = new Audi();
        Level4 myTestClass = new Level4();
        myTestClass.drive(car);
        myTestClass.drive(audi);
        myTestClass.drive(audiCar);
    }
}
```

### Level 5 
<a name="question-5"></a>
Concepts: Overloading + Overriding + Polymorphism
Question: What is the output of the below code?
```
package com.markbdsouza.polymorphism;

class Car {
    public int getSpeed() {return 100;}
}
class Audi extends Car {
    // overridden method as it already exists in the Car class
    public int getSpeed() {return 500;}
}
public class Level5 {
    public void drive(Car car) {
        System.out.println("Using a Car and driving at " + car.getSpeed());
    }
    // overloaded version of drive method
    public void drive(Audi audi) {
        System.out.println("Using an Audi and driving at " + audi.getSpeed());
    }
    public static void main(String[] args) {
        // Create 3 objects
        Car car = new Car();
        Audi audi = new Audi();
        Car audiCar = new Audi();
        // Testing overloading and overriding with polymorphism
        Level5 myTestClass = new Level5();
        myTestClass.drive(car);
        myTestClass.drive(audi);
        myTestClass.drive(audiCar);
    }
}
```

## Answers to the Quiz
### Level 1
This was simple and straight forward - Line 19 and Line 21 have issues. 
Since Dog, in its hierarchy chain implements Vertebrae, Eats and Movable, any of them can be used a reference variable and be assigned to an instance of Dog. But that does not mean they can access all Dog methods. 
```
        Movable a = new Dog(); 
        a.move(); 
        // a.eat(); // Compile Error - Moveable interface has only a move method
        Eats b = new Dog(); 
        // b.move(); // Compile Error -  Eats interface has only the eat method
        b.eat();
        Vertebrae c = new Dog(); 
        c.move(); // Has access to move method because Vertebrae exteds Movable 
        c.eat();  // Has access to eat method because Vertebrae exteds Eats
``` 
[Go back to Question-1](#question-1)

### Level 2
This was a trick question! If you guessed `swims` you're mistaken. You actually get a compiler error.
```
move() in com.markbdsouza.polymorphism.Fish cannot implement move() in com.markbdsouza.polymorphism.Movable
  attempting to assign weaker access privileges; was public
```
In an interface all methods are public and abstract by default. When a class tries to implement the method in the interface, it HAS to be PUBLIC as well. When overridding a method, we cannot make the method more restrictive. So the class implementation of the method has to be public. There are no 2 ways about it. 

[Go back to Question-2](#question-2)
### Level 3
The code does not compile. We get the error
```
move() in com.markbdsouza.polymorphism.Fish cannot override move() in com.markbdsouza.polymorphism.Animal
  overridden method does not throw java.io.EOFException
```
We can NOT throw checked exceptions(non Runtime exceptions) that are NEW or BROADER than those declared in the original overridden method. In this case the overridden method had a FileNotFoundException and the overriding method additionally has an EOFException. This is not allowed.
The overriding method can also throw narrower or fewer exceptions just not more! Note that the overriding method can however throw any unchecked (Runtime exception) that it wants. 
[Go back to Question-3](#question-3)

### Level 4
You might be surprised to see that the output is
```
Using a Car
Using an Audi
Using a Car
```
The choice of which overloaded that should be called is decided at compile time itself. The reference type (Type of the reference variable and not the actual type of the object it is pointing to) decides which overloaded method is invoked. 
When we use a reference type of Car, during compilation it is decided which overloaded method is invoked. This is why `Using a Car is picked up` 
[Go back to Question-4](#question-4)

### Level 5
Similar to Level 4 with a slight twist! 
```
Using a Car and driving at 100
Using an Audi and driving at 500
Using a Car and driving at 500
```
If you don't believe me run the code yourself and check ! 
Well you probably guessed line 1 and 2 correctly. In Line 3, what happens is even though the actual Object at runtime is an Audi Object and not just a Car object, the choice of which overloaded method that should be called is decided at compile time itself and not runtime. The reference type (Type of the reference variable and not the actual type of the object it is pointing to) decides which overloaded method is invoked. - _All similar to question 4_
So now we know that `Car audiCar = new Audi();` will invoke the below method
```
public void drive(Car car) {
        System.out.println("Using a Car and driving at " + car.getSpeed());
    }
```
We see that car.getSpeed() is called in the method and the compiler will throw no error during compilation because this method does in fact exist in the Car object.
But now during run time, the method that gets executed is the object type (type of the object that is used and not type of the reference variable). For our `Car audiCar = new Audi();` the type of the object is Audi. So during runtime the code that gets invoked is the below method 
```
public int getSpeed() {return 500;}
```
Merging these 2 concepts together of overloading and overriding we get the 3rd line as `Using a Car and driving at 500` !! Hope that all made sense
[Go back to Question-5](#question-5)

You will probably not use this sort of overloading + overriding with polymorphism in real life, so don't kill yourself if you didn't know the answer to the questions

_I hope you learnt something from this article!! If you know any java devs, ask them these questions and see if they get all of them right!!_