What this topic covers
15 subtopics- Overloading11
- Operator overloading6
- Overriding6
- Virtual functions5
- Basics4
- Duck typing3
- Dispatch2
- Design1
- Downcasting1
- Interfaces1
- Overriding rules1
- Parametric polymorphism1
Show all 15 subtopics
- Pattern matching1
- Static polymorphism1
- Upcasting1
- Beginner 15
- Intermediate 15
- Advanced 15
About this topic
Polymorphism lets one interface work with many types. Compile-time polymorphism (overloading, templates, generics) is decided by the compiler from the static types of the arguments. Run-time polymorphism (overriding, virtual functions) is decided by the object's actual class. Most trick questions mix the two: an overloaded method chosen by the declared type, or a default argument taken from the base class while the override runs. Every program here was run to produce its answer.
Free preview
Sample questions
Try each one first, then open the answer for the explanation and why the other options are wrong.
What does this print?
public class Main {
static class Animal { String sound() { return "..."; } }
static class Dog extends Animal { @Override String sound() { return "Woof"; } }
static class Cat extends Animal { @Override String sound() { return "Meow"; } }
static class Fish extends Animal { }
public static void main(String[] args) {
Animal[] zoo = { new Dog(), new Cat(), new Fish() };
StringBuilder out = new StringBuilder();
for (Animal a : zoo) out.append(a.sound()).append(' ');
System.out.println(out.toString().trim());
}
}
Show answer and explanation
Explanation
The loop only knows it has Animals, yet each call runs the method of the object's real class. Fish does not override, so it inherits Animal's version.
Why the other options are wrong
- AFish inherits "...".
- BEvery element is an Animal.
- COverrides are dispatched by the real type.
The variable holds a String but is declared as Object. What does this print?
public class Main {
static String show(Object o) { return "object"; }
static String show(String s) { return "string"; }
public static void main(String[] args) {
Object o = "hello";
String s = "hello";
System.out.println(show(o) + " " + show(s) + " " + show((String) o));
}
}
Show answer and explanation
Explanation
Overload selection uses the declared (static) type at compile time, not the object's run-time type. Only overriding is dynamic. A cast changes the static type.
Why the other options are wrong
- Ao is declared as Object.
- Cs is declared as String.
- DThe cast makes it a String.
Overloading and overriding together. What does this print?
public class Main {
static class Animal { String name() { return "animal"; } }
static class Dog extends Animal { @Override String name() { return "dog"; } }
static String vet(Animal a) { return "vet(Animal:" + a.name() + ")"; }
static String vet(Dog d) { return "vet(Dog:" + d.name() + ")"; }
public static void main(String[] args) {
Animal a = new Dog();
System.out.println(vet(a) + " " + vet(new Dog()));
}
}
Show answer and explanation
Explanation
Two decisions at two times: the compiler picks vet(Animal) from the declared type of a; at run time, a.name() is dispatched to Dog. Java is single-dispatch.
Why the other options are wrong
- Aname() is overridden.
- BThe overload is chosen from the static type.
- DBoth parts are reversed.