Inheritance and Polymorphism
Extend classes, override methods, and call the right behavior through a supertype reference when inheritance is appropriate.
Why it matters
Start from the concept, not the syntax
Meet a concrete situation where this idea earns its place, then state the boundary it guards.
Inheritance lets one class build on another, and polymorphism lets code written against the base type run the right specialized behavior. Together they replace type-checking if-chains with dispatch the runtime performs for you.
By the end of this chapter
Forgetting the super call or overriding by accident hides base behavior and breaks the is-a contract at runtime.
- extends and super
- Override
- Runtime dispatch
Mechanism
How Java expresses the concept
Walk the actual types, rules, and runtime behavior involved—the same behavior described in the Java Language Specification.
The mental model
`extends` creates an is-a relationship. A subclass inherits accessible fields and methods and can add its own or override behavior. Call the superclass constructor with `super(...)`; if you omit it, Java inserts `super()` and the superclass must have a no-arg constructor.
Method overriding replaces a superclass method in the subclass. The annotation `@Override` makes the compiler verify the signature matches. At runtime, the JVM picks the method based on the actual object type, not the reference type: that is polymorphism.
`instanceof` tests the runtime type before a cast. Prefer designing with interfaces over deep inheritance; a long chain of overrides is hard to reason about. `abstract` classes cannot be instantiated and can hold abstract methods that subclasses must implement.
Constructors are not inherited and are not polymorphic: the version that runs is chosen by the class being constructed. Field hiding (a subclass field with the same name as a superclass field) is legal but confusing; avoid it.
Concept map
Inspect the building blocks as a whole
Use the map as a structural reference; it shows the pieces and their relationships, not an execution sequence.
Core Java
Inheritance and polymorphism
A subclass extends a superclass to reuse and specialize behavior. Polymorphism lets code target the supertype and run the right override.
- 01is-a relationship
- 02super constructor call
- 03Override and polymorphism
- 04instanceof before cast
- 05abstract classes
- 06No polymorphic constructors
Implementation
Encode the smallest runnable example
Write and run the code, then observe the behavior you just predicted with a real Java program.
Runnable snippet path
Predict, run, and change each example
Override and polymorph
The same draw() call runs the subclass version because the JVM uses the real type.
abstract class Shape {
abstract String draw();
}
class Circle extends Shape {
@Override String draw() { return "circle"; }
}
class Square extends Shape {
@Override String draw() { return "square"; }
}
class Demo {
static void print(Shape s) { System.out.println(s.draw()); }
}Remember
Code to the supertype (Shape) and let the runtime pick the override.
Change one input, predict the result, then compile or test it before continuing.
instanceof guard
Check the type before casting to avoid ClassCastException.
static void describe(Shape s) {
if (s instanceof Circle c) {
System.out.println("radius shape: " + c.draw());
}
}Remember
Pattern matching with instanceof both checks and binds the variable.
Change one input, predict the result, then compile or test it before continuing.
Watch out
Break it on purpose, then repair the right layer
Predict the symptom before running the failure case, and close with the completion checklist.
Deliberate failure
Break
Omit the super call when a subclass depends on base initialization
Observe
The object is half-built and inherited fields stay at defaults
Repair
Call super first when the subclass relies on base state, and annotate every override with @Override
Why it matters
Call super first when the subclass relies on base state, and annotate every override with @Override
Completion checklist
- Use extends for an is-a relationship
- Override methods with @Override
- Dispatch through a supertype reference
Go deeper
Official references
The primary sources behind this chapter. Every claim above stays consistent with them.