1. What is inheritance?
Inheritance is a mechanism that allows you to create a new class based on an existing one, “inheriting” its properties and methods. The new class is called a subclass (or child class), and the original is the parent class (or base class).
It’s like making a new cake based on an old recipe: you take all the best parts, add a couple of new ingredients — and voilà, you’ve got “Grandma’s Recipe Cake with a Secret Ingredient.”
- Parent class — contains common properties and behavior.
- Subclass — inherits all that, plus can add something of its own or change behavior.
For example, “Cat is an Animal”: all cats are animals, but not all animals are cats. Animal can be the base class, and Cat its subclass. The same goes for Dog, for instance.
Or “Circle is a Shape”: every circle is a shape, but not every shape is a circle. Shape can be the parent class, and Circle and Triangle its subclasses. In Java these relationships are implemented using the extends keyword.
Why do we need inheritance?
The million-dollar question: why not just copy code from one class to another? Why was inheritance invented at all?
- Code reuse: Everything common is extracted into a base class. There’s no need to duplicate fields and methods — they automatically appear in subclasses. For example, in a university app, the base class could be a person, who has at least a name and a date of birth, and “student” and “teacher” are subclasses with their own properties.
- Extension and specialization: You can add new properties and methods or change existing ones only where needed. All animals make sounds, but a cat will meow and a dog will bark. At the same time, a cat can be given the ability to climb trees (which the base class doesn’t have).
- Structured hierarchies: Code becomes more logical and easier to understand. For example, if you have classes Animal, Dog, Cat, it’s obvious that Dog and Cat are specific cases of Animal.
Example. If Java didn’t have inheritance, you’d have to copy methods like eat(), sleep() and the name field into every animal class. And if tomorrow you need to add a breathe() method, you’d have to change dozens of classes! With inheritance, it’s enough to add the ability to breathe to the base class.
2. Inheritance syntax: extends
How do you declare inheritance in Java? It’s very simple: use the extends keyword.
class ParentClass {
// fields and methods
}
class Subclass extends ParentClass {
// additional fields and methods
}
Example 1: Animals
// Parent class
class Animal {
String name;
void eat() {
System.out.println(name + " eats.");
}
}
// Subclass
class Cat extends Animal {
void meow() {
System.out.println(name + " says: Meow!");
}
}
What’s happening here?
- The Cat class inherits all fields and methods of the Animal class.
- This means Cat already has the name field and the eat() method, even though we didn’t write them explicitly.
- Plus Cat gets its own method, meow().
Usage
public class Main {
public static void main(String[] args) {
Cat kitty = new Cat();
kitty.name = "Barsik";
kitty.eat(); // Barsik eats. (inherited)
kitty.meow(); // Barsik says: Meow! (own method)
}
}
Voilà! We got a new class with minimal code, avoiding duplication.
3. What exactly does a subclass inherit?
In Java, a subclass inherits:
- All public (public) and protected (protected) fields and methods of the base class.
- All package-private fields and methods if the subclass is in the same package.
Does not inherit:
- Constructors (they need to be explicitly declared in the subclass).
- Private (private) fields and methods (they are accessible only inside the base class itself).
- Static initialization blocks (they are not inherited, but each class can have its own).
- Members with package-private access if the subclass is in a different package.
Illustration
class Animal {
public String name;
private int age;
public void eat() {
System.out.println("Eating");
}
private void secret() {
System.out.println("Secret!");
}
}
class Dog extends Animal {
public void bark() {
System.out.println("Woof!");
}
}
- Dog will inherit the name field and the eat() method.
- Dog cannot see the age field or the secret() method — they are private.
4. Inheritance limitations in Java
Java is fairly strict, and it has its own rules:
Only single class inheritance: each class can extend only one other class. But a class can have any number of subclasses.
class Dog extends Animal { ... } // OK
class Dog extends Animal, Pet { ... } // Error! Not allowed
Multiple inheritance of interfaces is allowed — but that’s a separate topic, and we’ll talk about it later.
The Object class is the ancestor of all classes in Java. Even if you don’t explicitly write extends, your class still implicitly extends Object.
5. Practical example
Let’s keep building our “zoological” app.
Step 1. Base class Animal
class Animal {
String name;
void eat() {
System.out.println(name + " eats.");
}
}
Step 2. Subclass Cat
class Cat extends Animal {
void meow() {
System.out.println(name + " says: Meow!");
}
}
Step 3. Subclass Dog
class Dog extends Animal {
void bark() {
System.out.println(name + " says: Woof!");
}
}
Step 4. Use the classes
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.name = "Murka";
cat.eat(); // Murka eats.
cat.meow(); // Murka says: Meow!
Dog dog = new Dog();
dog.name = "Sharik";
dog.eat(); // Sharik eats.
dog.bark(); // Sharik says: Woof!
}
}
What did we get?
- Both Cat and Dog use the common name field and eat() method from the base class.
- Each class adds its own unique behavior: meow() for the cat, bark() for the dog.
- If you need to change how animals eat, it’s enough to modify the eat() method in Animal — the changes will automatically apply to all subclasses.
6. Useful nuances
Visualization: class hierarchy
You can imagine the hierarchy like this:
. Animal
/ \
Cat Dog
- Animal is the base class and contains everything common to animals.
- Cat and Dog are subclasses and add unique features.
A bit about constructors and inheritance
Constructors are not inherited. If you don’t define a constructor in a subclass, Java automatically adds a no-arg constructor (if the parent has one). If the parent class only has a constructor with parameters, then in the subclass you need to call it explicitly via super(...). A short example:
class Animal {
String name;
Animal(String name) {
this.name = name;
}
}
class Cat extends Animal {
Cat(String name) {
super(name); // call the parent constructor
}
}
7. Common mistakes when using inheritance
Error No. 1: Trying to extend multiple classes at once.
In Java you cannot write class Cat extends Animal, Pet. Only one parent!
Error No. 2: Expecting private fields and methods to be accessible in a subclass.
Private members are not inherited (more precisely, they exist but are not accessible from the subclass). Use protected if you want to give access to subclasses.
Error No. 3: Forgetting to call the parent constructor.
If the base class has no no-arg constructor and you don’t explicitly call super(...), you’ll get a compilation error.
Error No. 4: Using inheritance “just to save code” rather than by meaning.
If there’s no “is-a” relationship (is-a) between classes, it’s better not to use inheritance. For example, “Person” should not extend “Car,” even if they both have a speed field.
GO TO FULL VERSION