Module lessons (1/2)
Inheritance
Inheritance is a fundamental mechanism of OOP that allows a class (called a child class or subclass) to inherit fields and methods from another class (called a parent class or superclass).
This promotes code reuse and avoids unnecessary repetition.
Extending a Class with extends
In Java, we use the extends keyword to indicate that a class inherits from another:
class Vehicle {
protected int speed; // 'protected' makes the field visible to subclasses
public void honk() {
System.out.println("Beep beep!");
}
}
class Car extends Vehicle {
// Car automatically inherits the speed field and the honk() method
}
The Constructor and the super() Keyword
If the superclass has a constructor that accepts parameters, the subclass must call it explicitly in its constructor using super(...) as the very first statement:
class Person {
String name;
public Person(String name) {
this.name = name;
}
}
class Student extends Person {
int studentId;
public Student(String name, int studentId) {
super(name); // Invokes the constructor of Person
this.studentId = studentId;
}
}
Method Overriding (@Override)
A subclass can provide its own specific implementation for a method inherited from the superclass. This operation is called overriding (method overriding) and is indicated by the @Override annotation.
class Animal {
public void makeSound() {
System.out.println("Rumore generico");
}
}
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Miao!");
}
}
The protected Modifier
The protected access modifier plays a key role in inheritance. Unlike private, which makes members visible only within the same class, protected allows access to fields and methods both within the same package and by all subclasses, even if they reside in different packages.
Accessing Parent Members with super
In addition to calling the superclass constructor, the super keyword can be used within subclass methods to reference methods or variables of the parent class. This is particularly useful when a method is overridden, but you still want to invoke the original parent behavior:
class Animal {
public void sleep() {
System.out.println("Zzz");
}
}
class Cat extends Animal {
@Override
public void sleep() {
super.sleep(); // Executes the behavior of Animal
System.out.println("The cat purrs while sleeping.");
}
}
Single Inheritance in Java
In Java, a class can extend only one class (single inheritance). Direct inheritance from multiple classes (multiple inheritance) is not allowed; for example, class Cat extends Animal, Mammal will cause a compilation error. This design choice avoids ambiguities known as the "diamond problem" (when two superclasses define the same method with different implementations). To overcome this limitation, Java introduces the concept of Interfaces, which we will explore in the next module.
Try it yourself
Complete the Dog subclass by extending Animal. Declare the Dog constructor that accepts a name (String) and uses super(name) to pass it to the Animal constructor.
Show hint
Write `public Dog(String name) { super(name); }` inside the Dog class.
Solution available after 3 attempts
Extend Dog from Animal and override the makeSound() method so that it returns the string Woof instead of Generic Sound. Use the @Override annotation.
Show hint
Write `@Override` above the declaration `public String makeSound() { return 'Woof'; }` inside Dog.
Solution available after 3 attempts
Declare a Cat class that extends Animal and overrides the makeSound() method to return the string Meow. The Animal class already has a constructor that accepts a name; ensure that the Cat constructor also accepts a name and correctly passes it to the superclass constructor.
Show hint
Create the `Cat` class extending `Animal`. Declare the constructor `public Cat(String name) { super(name); }` and override the `makeSound()` method using `@Override` to return `'Meow'`.
Solution available after 3 attempts