Chapter 8 of 16Foundation

Inheritance and Polymorphism

Extend classes, override methods, and call the right behavior through a supertype reference when inheritance is appropriate.

30 minJava 21
01

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
02

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.

03

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.

  1. 01is-a relationship
  2. 02super constructor call
  3. 03Override and polymorphism
  4. 04instanceof before cast
  5. 05abstract classes
  6. 06No polymorphic constructors
04

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

2 focused examples
01

Override and polymorph

The same draw() call runs the subclass version because the JVM uses the real type.

Shape.java
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.

02

instanceof guard

Check the type before casting to avoid ClassCastException.

Guard.java
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.

05

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

  1. Break

    Omit the super call when a subclass depends on base initialization

  2. Observe

    The object is half-built and inherited fields stay at defaults

  3. 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
06

Go deeper

Official references

The primary sources behind this chapter. Every claim above stays consistent with them.