Inheritance, Superclass, Subclass

What Inheritance Does

Inheritance lets one class inherit fields and methods from another. The class being inherited from is the superclass (or parent class); the class doing the inheriting is the subclass (or child class). The parts of an FRC robot — an intake, a shooter, a climber — share real structure: each has a name for logging, a way to print a labeled message, and a stop() method. That makes them a natural fit for a shared superclass. Chapters 17 and 18 use one such superclass, RobotPart, throughout:

public class RobotPart
{
    private String name;

    public RobotPart(String name) { this.name = name; }
    public String getName() { return name; }
    public void log(String msg) { System.out.println("[" + name + "] " + msg); }
    public void stop() { log("stopped"); }
}

public class Intake extends RobotPart
{
    // passes the name up to RobotPart's constructor (Lesson 17.2)
    public Intake(String name) { super(name); }

    // inherits getName(), log(), and stop() for free
}

RobotPart is the team's own class, written for this course — it isn't part of WPILib. This is its one full definition: later lessons show only what they add to it.

extends is the keyword that sets up inheritance. Intake's one line of its own, the constructor, hands the name up to RobotPart with super(name) — Lesson 17.2 explains exactly how that works. A Java class can only extends one superclass — unlike a person with two biological parents, there's no multiple inheritance of this kind in Java. Omitting extends entirely doesn't mean "no parent" — it means the class implicitly inherits from Java's built-in Object class (Lesson 17.4).

The is-a Relationship

Inheritance should only model a genuine is-a relationship: an Intake is a RobotPart, a Climber is a RobotPart. The test to apply: could you substitute the subclass anywhere the superclass is expected, and have it still make sense? A Vision processor being asked to stop() and get log()ed makes sense as a RobotPart — but a Robot class itself, or a Controller wrapping a joystick, isn't a kind of RobotPart, even if it happens to interact with one.

is-a vs. has-a

The has-a relationship (also called association) is different: it's when one class simply holds a reference to another, without being a specialized kind of it. A Robot has a Drivetrain, an Intake, and a Shooter — it isn't a subclass of any of them:

public class Robot
{
    private Drivetrain drivetrain;  // has-a: Robot holds a Drivetrain, isn't one
    private Intake intake;          // has-a
}

Compare that to Intake extends RobotPart — that's is-a: an Intake really is a specialized kind of RobotPart, not just something that happens to reference one.

Why Bother

Two forces motivate reaching for a superclass:

  • Generalization — several classes already share data/behavior, so pull the shared parts up into one common parent. Intake, Shooter, and Climber all need a name, a log() method, and a stop() method — that's exactly what RobotPart is for.
  • Specialization — a class wants most of a parent's behavior, but needs to add something of its own or do one thing differently. Intake inherits log() unchanged, but will eventually want its own stop() that's specific to its own rollers — replacing an inherited method like that is called overriding (Lesson 18.1).

Common Pitfalls

  • Using inheritance purely to reuse code, without a real is-a relationship. If the substitution test fails — the subclass wouldn't actually make sense wherever the superclass is expected — model it as has-a (a field) instead of extends.
  • Forgetting a class always has exactly one superclass. Omitting extends doesn't mean "no parent" — it means the implicit parent is Object (Lesson 17.4).
  • Assuming a class can extend more than one class. class Intake extends RobotPart, Loggable doesn't compile — Java allows only one extends, though a class can implements multiple interfaces (Ch.19).

Key Takeaways

  • extends declares inheritance: the subclass gains the superclass's fields and methods.
  • A class can only extends one superclass; omitting extends implicitly means extending Object.
  • Use inheritance only for a genuine is-a relationship — verify with the substitution test (does the subclass make sense wherever the superclass is expected?).
  • has-a (association: one class simply holding a reference to another) is the right model when is-a doesn't genuinely apply.

Derived from csawesome-2026: unit-5-inheritance-optional/5.01-inheritance-superclass-subclass.md (CSA 5.1) Deck context: mechacoder-test/src/lessons/java-2.js, slide 4 ("Inheritance & Abstractions")