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). Every FRC robot's subsystems share real structure — a name for logging, a stop() method, a periodic() method WPILib calls every loop — which makes them a natural fit for a shared superclass:
public abstract class Subsystem
{
private String name;
public Subsystem(String name) { this.name = name; }
public String getName() { return name; }
public void log(String msg) { System.out.println("[" + name + "] " + msg); }
}
public class Intake extends Subsystem
{
// inherits getName() and log() for free
}
extends is the keyword that sets up inheritance. 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 Subsystem, a Climber is a Subsystem. 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 Subsystem — but a Robot class itself, or a Controller wrapping a joystick, isn't a kind of Subsystem, 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 Subsystem — that's is-a: an Intake really is a specialized kind of Subsystem, 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, andClimberall need a name and alog()method — that's exactly whatSubsystemis for. - Specialization — a class wants most of a parent's behavior, but needs to add something of its own or do one thing differently.
Intakeinheritslog()unchanged, but still needs its ownstop()that's specific to its own motor.
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
extendsdoesn't mean "no parent" — it means the implicit parent isObject(Lesson 17.4). - Assuming a class can extend more than one class.
class Intake extends Subsystem, Loggabledoesn't compile — Java allows only oneextends, though a class canimplementmultiple interfaces.
Key Takeaways
extendsdeclares inheritance: the subclass gains the superclass's fields and methods.- A class can only
extendsone superclass; omittingextendsimplicitly means extendingObject. - 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")