Inheritance
Inheritance lets you build a new class on top of an existing one. The new class gets the fields and methods of its parent and can add its own or change the inherited ones.
extends
A child class is declared with the extends keyword. The parent is called the superclass, and the child the subclass:
class Animal {
String name;
String describe() {
return name + " is an animal";
}
}
class Dog extends Animal {
String bark() {
return name + ": Woof!";
}
}
void main() {
Dog dog = new Dog();
dog.name = "Rex";
IO.println(dog.describe());
IO.println(dog.bark());
}Output:
Rex is an animal
Rex: Woof!Dog has no name field or describe() method of its own — they come from Animal.
The constructor and super(...)
Constructors are not inherited. A subclass constructor calls the parent constructor with super(...), passing it the data it needs:
class Animal {
protected String name;
Animal(String name) {
this.name = name;
}
}
class Cat extends Animal {
Cat(String name) {
super(name);
}
String meow() {
return name + ": Meow";
}
}
void main() {
IO.println(new Cat("Kitty").meow());
}Output:
Kitty: MeowThe protected modifier opens a field to subclasses and to classes in the same package, but not to the rest of the code. Packages are covered at the end of the chapter.
Overriding methods
A subclass may declare a method with the same signature as the parent's — then its version is the one that gets called. This is called overriding. The @Override annotation asks the compiler to check that the parent really has such a method:
class Animal {
String sound() {
return "...";
}
}
class Dog extends Animal {
@Override
String sound() {
return "Woof";
}
}
void main() {
IO.println(new Animal().sound());
IO.println(new Dog().sound());
}Output:
...
WoofCalling the parent's version
With super.method() a subclass calls the parent's version of a method and extends it instead of rewriting everything:
class Product {
String label() {
return "Product";
}
}
class Book extends Product {
@Override
String label() {
return super.label() + " / Book";
}
}
void main() {
IO.println(new Book().label());
}Output:
Product / BookOne parent and the Object class
In Java a class can have only one direct parent. If extends is not written, the parent is the Object class — the root of the whole hierarchy. That is why every object has the toString() and equals() methods: they are inherited from Object. A class marked final forbids inheriting from it — String is built this way, for example.
Common mistake
If the parent has only a constructor with parameters, the subclass must call it with super(...). Without that, Java tries to call a constructor without parameters, which does not exist:
class Animal {
String name;
Animal(String name) {
this.name = name;
}
}
class Dog extends Animal {
Dog() {
IO.println("Creating a dog");
}
}
void main() {
new Dog();
}Output:
Main.java:10: error: constructor Animal in class Main.Animal cannot be applied to given types;
Dog() {
^Add super("Rex"); or pass the name through a parameter of the Dog constructor.