Inheritance
Inheritance lets one class build on another. A SavingsAccount is a kind of Account: it has everything an account has, plus interest. The new class (subclass) inherits fields and methods from the existing one (superclass), adds its own, and can change inherited behaviour.
extends
class Animal { String name; Animal(String name) { this.name = name; } void eat() { System.out.println(name + " is eating"); } } class Dog extends Animal { Dog(String name) { super(name); } void fetch() { System.out.println(name + " fetches the ball"); } } public class Main { public static void main(String[] args) { Dog rex = new Dog("Rex"); rex.eat(); rex.fetch(); } }
Rex is eating Rex fetches the ball
Dog extends Animal: a Dog has the name field and eat method from Animal, plus its own fetch. A class can extend only one class.
super(…) in constructors
A subclass constructor must first initialise the superclass part of the object by calling super(…). If you don't write it, Java inserts super() — which fails to compile when the superclass has no no-argument constructor:
class Vehicle { final String plate; Vehicle(String plate) { this.plate = plate; } } class Car extends Vehicle { Car() { } } public class Main { public static void main(String[] args) { } }
Main.java:7: error: constructor Vehicle in class Vehicle cannot be applied to given types;
Overriding methods
class Account { protected double balance; Account(double balance) { this.balance = balance; } double monthlyFee() { return 2.0; } void endOfMonth() { balance -= monthlyFee(); } } class StudentAccount extends Account { StudentAccount(double balance) { super(balance); } @Override double monthlyFee() { return 0.0; } } public class Main { public static void main(String[] args) { Account regular = new Account(100); Account student = new StudentAccount(100); regular.endOfMonth(); student.endOfMonth(); System.out.println(regular.balance + " / " + student.balance); } }
98.0 / 100.0
A subclass can override a method by declaring one with the same signature. endOfMonth, inherited unchanged, calls whichever monthlyFee belongs to the actual object. @Override asks the compiler to check that you really are overriding something — it catches typos like monthlyfee.
Calling the parent's version
class Employee { String name; double salary; Employee(String name, double salary) { this.name = name; this.salary = salary; } String describe() { return name + " earns " + salary; } } class Manager extends Employee { int reports; Manager(String name, double salary, int reports) { super(name, salary); this.reports = reports; } @Override String describe() { return super.describe() + " and manages " + reports + " people"; } } public class Main { public static void main(String[] args) { System.out.println(new Manager("Mei", 98000, 3).describe()); } }
Mei earns 98000.0 and manages 3 people
super.method() calls the superclass's version, so an override can extend behaviour rather than replace it.
protected
protected members are visible to subclasses (and the same package). It's handy for things subclasses legitimately need, but it exposes internals to every subclass — keep fields private and offer protected methods when you can.
final classes and methods
final class Money { } class FakeMoney extends Money { } public class Main { public static void main(String[] args) { } }
Main.java:4: error: cannot inherit from final Money
A final class can't be extended (String is final), and a final method can't be overridden. Use it to protect classes whose behaviour must not change.
Every class extends Object
A class without extends implicitly extends java.lang.Object, the root of the class hierarchy. That's where toString, equals and hashCode come from (lesson 35).
Inheritance or composition?
Use inheritance only for genuine "is-a" relationships where the subclass can be used anywhere the superclass is expected. For "has-a" relationships — a car has an engine — store an object in a field instead (composition). Deep inheritance trees make code rigid; composition and interfaces (lesson 31) are usually more flexible.
Try it yourself
Create shapes that inherit a describe method but provide their own area.
circle with area 12.57 square with area 9.00