Step 1 of 7 · Reading · ~3 min
Learn
Inheritance and Interfaces
Inheritance and super
Inheritance lets a class reuse another class's fields and methods and change only what differs. By the end of this lesson you can write a subclass, override a method (and still call the parent's version), and explain why a variable typed as the parent runs the child's code.
A parent and two children
static class Vehicle {
protected String plate;
protected int wheels;
Vehicle(String plate, int wheels) {
this.plate = plate;
this.wheels = wheels;
}
int toll() {
return 2 * wheels;
}
String label() {
return plate + " pays " + toll();
}
}
static class Truck extends Vehicle {
private int axles;
Truck(String plate, int axles) {
super(plate, 2 * axles); // run the parent's constructor first
this.axles = axles;
}
@Override
int toll() {
return super.toll() + 10 * axles;
}
}
extends makes Truck a subclass of Vehicle: a Truck is a Vehicle, and automatically has plate, wheels, toll() and label(), plus whatever it adds.
super(...) in a constructor
The parent's fields must be initialized by the parent's constructor. super(args) calls it, and it must be the first statement. If you write no super(...) call, Java inserts a hidden super() for you; when the parent has no no-argument constructor, that is a compile error, so you must call a real one explicitly.
Overriding and @Override
A subclass overrides an inherited method by declaring one with the same name and parameters. Always add @Override: if the signature does not actually match a parent method (a typo, a wrong parameter type), the compiler errors instead of silently creating a second, unrelated method.
super.method(): extend instead of replace
Inside an override, super.toll() runs the parent's version. That is how a subclass adds to the parent's behavior rather than rewriting it. Leave out super. and toll() calls itself: infinite recursion, ending in a StackOverflowError.
Polymorphism
A variable of the parent type can hold any subclass object, and the actual object's version of an overridden method runs:
Vehicle[] fleet = { new Vehicle("CAR-1", 4), new Truck("TRK-9", 3) };
for (Vehicle v : fleet) {
System.out.println(v.label());
}
CAR-1 pays 8
TRK-9 pays 42
The loop knows only Vehicle, yet the second line used Truck.toll(). Java picks the method at run time from the object's real class: dynamic dispatch. Notice that label() is written only in Vehicle, but it calls toll(), and that call also dispatches to the subclass. Code written against the parent works unchanged for every child, including ones that do not exist yet.
Calls are checked against the declared type, though. Through a Vehicle variable you can only call methods Vehicle has, even when the object is a Truck.
Access and final
privatemembers belong to the class alone; a subclass cannot touch them.protectedmembers are visible to subclasses (and the same package).finalon a method forbids overriding it; on a class it forbids subclassing.
Java has single inheritance: one parent per class. Sharing behavior across unrelated classes is the job of interfaces, in the next lesson. Deep hierarchies are hard to keep correct, so reach for inheritance only when the child truly is a kind of the parent.
Common mistakes
- No
super(...)call when the parent lacks a no-argument constructor. - Omitting
@Override, so a misspelled method name quietly adds a new method. - Calling
toll()insidetoll()instead ofsuper.toll(). - Redeclaring a parent's field in the child instead of reusing it, which creates two separate variables.
Your exercise
A payroll program holds a mix of staff in one array typed as the parent class. Each kind of employee pays differently; the base class and the printing code already work against the parent type. You supply the subclass behavior, one of which extends the parent's rule and one of which replaces it.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…