The idea
Many things are kinds of other things: a puppy is a dog, a car is a vehicle, a manager is an employee. Inheritance models that "is-a" relationship in code. A child class (also called a subclass) is declared from a parent class (the superclass). It receives the parent's fields and methods automatically and can add its own, so you reuse code instead of copying it.
The syntax
You write extends and the parent's name after the child's name:
class Puppy extends Dog {
}
Even this empty body is meaningful: Puppy already has everything Dog has. In Java a class can extend exactly one other class, though a chain is fine, such as Puppy extending Dog and Dog extending Animal.
What gets inherited
- Fields. A
Puppyhas anamefield although onlyDogdeclares it. - Methods. A
Puppycan callbark()although onlyDogdefines it. - The type. Anywhere the code expects a
Dog, you can supply aPuppy, because every puppy is a dog. The polymorphism lesson builds on this.
One limit applies: private members of the parent exist in the child object but cannot be named directly in the child's code. A parent that wants to share a field with its children uses protected or public, or offers a getter. Constructors are never inherited.
What you still write
- A constructor, which usually passes its arguments to the parent's constructor, because the parent's fields still need to be initialized.
- Any new methods and fields that only the child has.
Calling the parent's constructor with super
Every constructor starts by running a constructor of its parent. If you don't say which, Java quietly inserts a call to the parent's no-argument constructor. That works only if the parent has one. The Dog class in this lesson has a single constructor, Dog(String name), so Java has no no-argument version to call and the compiler stops with an error. You fix it by calling the right parent constructor yourself with super(...):
public Puppy(String name) {
super(name);
}
super(name) runs Dog's constructor, which stores the name. It must be the first statement of the constructor, because the parent part of the object has to be built before the child's part.
Without it, a child like this fails to compile:
class Kit extends Dog { }
The compiler reports that constructor Dog in class Dog cannot be applied to the given types, and that the required argument is a String.
The lesson's exercise, step by step
The starter code supplies Dog, with a public name, a constructor and a bark method, and a mainFunction that uses a Puppy. You create the class:
- Declare
Puppywithextends DogbelowDog, so it reuses thenamefield and thebarkmethod. Give it a public constructor that takes aString nameand callssuper(name). - Add the new behavior. Inside
Puppy, below the constructor, writepublic void whine()and print"whimper".barkis inherited, so only the new method is needed.
The complete program:
class Dog {
public String name;
public Dog(String name) { this.name = name; }
public void bark() {
System.out.println("Woof! I am " + name);
}
}
class Puppy extends Dog {
public Puppy(String name) { super(name); }
public void whine() {
System.out.println("whimper");
}
}
class Solution {
public void mainFunction() {
Puppy buddy = new Puppy("Buddy");
buddy.bark();
buddy.whine();
}
}
The output shows both an inherited method and a new one:
Woof! I am Buddy
whimper
The call buddy.bark() finds no bark in Puppy, so Java looks in the parent and runs Dog's version. It prints the name that super(name) stored.
Details worth knowing
- One direction only. A
Puppycan use everything inDog, but a plainDogdoesn't havewhine(). Callingwhine()on a variable of typeDogdoesn't compile. - Every class has a parent. A class with no
extendsclause extendsObject, which is where methods such astoString()andequals(...)come from. - Inheritance is for "is-a". Use it when the child really is a kind of the parent. When one object merely has another, as a dog has a name, store it in a field instead.
- The child may change inherited behavior. That is overriding, which the next lesson covers.
Common mistakes
- Omitting
super(name). When the parent has no no-argument constructor, the child's constructor can't compile without an explicitsuper(...)call. - Putting
super(...)second. It has to be the first statement in the constructor, before anything else. - Redeclaring the parent's field. Writing
public String name;again inPuppycreates a second field that hides the first. Reuse the inherited one. - Copying methods instead of inheriting them. If
Puppydefines its ownbarkwith the same text, the duplication is what inheritance exists to avoid. - Extending more than one class.
class Puppy extends Dog, Petis not allowed in Java.
Key takeaways
class Child extends Parentgives the child the parent's accessible fields and methods.- The child can add new fields and methods of its own.
- A constructor is not inherited, and the child's constructor normally calls
super(...)as its first statement. - A
Puppycan be used wherever aDogis expected. - Use inheritance for "is-a" relationships.