What this topic covers
17 subtopics- Multiple inheritance9
- Constructor order5
- super4
- Access in subclasses3
- Basics3
- Hiding3
- Method resolution3
- Restricting inheritance3
- Design2
- Overriding rules2
- Type checks2
- Destructors1
Show all 17 subtopics
- Fragile base class1
- Liskov substitution1
- Mixins1
- Slicing1
- Types of inheritance1
- Beginner 15
- Intermediate 15
- Advanced 15
About this topic
Inheritance lets a class reuse and specialise another: a Car is a Vehicle. Output puzzles test the order in which constructors and destructors run, what super calls, and which members are actually polymorphic – methods are, but fields and static methods are only hidden. Multiple inheritance brings the diamond problem, solved differently by C++ (virtual bases), Java (interfaces with default methods) and Python (the method resolution order). Hierarchies are drawn as UML class diagrams.
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 Vehicle { Vehicle() { System.out.print("Vehicle "); } }
static class Car extends Vehicle { Car() { System.out.print("Car "); } }
static class SportsCar extends Car { SportsCar() { System.out.print("SportsCar "); } }
public static void main(String[] args) {
new SportsCar();
}
}
Show answer and explanation
Explanation
Every constructor first calls its parent's constructor (an implicit super()), so construction runs from the top of the hierarchy down.
Why the other options are wrong
- ACar's constructor is not skipped.
- BParents are built before children.
- CThe parent constructors run too.
Both classes declare a field name. What does this print?
public class Main {
static class Parent {
String name = "parent";
String getName() { return name; }
}
static class Child extends Parent {
String name = "child";
@Override String getName() { return name; }
}
public static void main(String[] args) {
Parent p = new Child();
System.out.println(p.name + " " + p.getName() + " " + ((Child) p).name);
}
}
Show answer and explanation
Explanation
Fields are not polymorphic: p.name is chosen by the reference type (Parent). Methods are dispatched by the object's real type. The Child object actually holds two separate name fields.
Why the other options are wrong
- AgetName is overridden.
- BThe cast selects Child's field.
- CField access uses the static type.
Two interfaces provide the same default method. What does this print?
public class Main {
interface Walker { default String move() { return "walk"; } }
interface Swimmer { default String move() { return "swim"; } }
static class Duck implements Walker, Swimmer {
@Override public String move() {
return Walker.super.move() + "+" + Swimmer.super.move();
}
}
public static void main(String[] args) {
Walker w = new Duck();
System.out.println(w.move());
}
}
Show answer and explanation
Explanation
When two interfaces supply conflicting defaults, the class must override the method (otherwise it does not compile) and can call either one with Interface.super.method(). That is Java's answer to the diamond problem.
Why the other options are wrong
- AThe explicit override resolves the conflict.
- CThe override combines both.
- DThe override combines both.