dev only

Inheritance and Constructors

Constructors Are Never Inherited

A subclass inherits its superclass's public methods and fields, but it does not inherit constructors, and it can't directly touch the superclass's private fields. Yet those inherited private fields still need to be properly set up before anything uses them — so how does a subclass initialize state that belongs to its superclass?

The super(...) Call

The keyword super, used like a method call, runs the superclass's constructor code in the context of the object already being built:

public class Subsystem
{
    private String name;

    public Subsystem(String name) { this.name = name; }
    public String getName() { return name; }
}

public class Intake extends Subsystem
{
    private boolean hasGamePiece;

    public Intake(String name)
    {
        super(name);          // runs Subsystem's constructor, setting the private `name` field
        hasGamePiece = false;  // Intake's own field
    }
}

super(name) isn't creating a second object — it's the one and only way to run Subsystem's own initialization logic for the object currently under construction. Without it, name would never get set, since Intake has no direct access to that private field to assign it itself.

The Implicit super() Call

If a constructor doesn't start with an explicit super(...) call, Java automatically inserts a no-argument super() call for you. That only works if the superclass actually has a no-argument constructor — if it doesn't, any subclass constructor must explicitly call super(...) with arguments matching a constructor that does exist, or the code won't compile.

The Chain Bottoms Out at Object

Whether called explicitly or inserted implicitly, every chain of super calls eventually reaches java.lang.Object's own no-argument constructor — the one class with no superclass of its own (Lesson 17.4). From there, construction "unwinds": Object's constructor logic runs first, then each class going back down the hierarchy, ending with whichever class was actually instantiated. By the time your own constructor's body runs, every inherited field further up the chain has already been properly initialized.

Intake intake = new Intake("Front Intake");
// Order of execution: Object() -> Subsystem(String) -> Intake(String)

Common Pitfalls

  • Trying to assign a superclass's private field directly. this.name = name; inside Intake's constructor doesn't compile if name is private in Subsystem — only super(name) can reach it.
  • Forgetting super(...) must be the first statement. A subclass constructor calling super(...) after other statements doesn't compile — it must be the very first line, since the superclass has to finish initializing before the subclass's own code can safely run.
  • Assuming a no-argument super() always works. If the superclass has no no-argument constructor (only ones taking parameters), Java can't insert an implicit call — the subclass must explicitly call super(...) with matching arguments.

Key Takeaways

  • Constructors are never inherited — only a super(...) call can run the superclass's constructor logic to initialize its own (even private) fields.
  • If a subclass constructor doesn't call super(...) explicitly, Java inserts a no-argument super() call automatically — which only works if the superclass has one.
  • Every construction chain eventually reaches Object's constructor, which runs first; the subclass's own code only runs after every class above it has finished initializing.

Derived from csawesome-2026: unit-5-inheritance-optional/5.02-inheritance-and-constructors.md (CSA 5.2)