In object-oriented programming (OOP), Inheritance allows reusing of software by extending an existing class members. When creating a new class, you may want the new class to inherit the properties and members of an existing class instead of implementing the same proprieties and members again in the new class. Here, the existing class is called the superclass, and the new class is called the subclass.
For example, a Circle is a Shape. Thus, in Java, class Circle can be said to inherit from class Shape. In this context, class Shape is a superclass and class Circle is a subclass. Some inheritance examples (superclass:subclasses):
- Student: GraduateStudent, UndergraduateStudent
- Shape: Circle, Triangle, Rectangle, Sphere, Cube
- Bank Account: Checking Account, Savings Account
- Vehicle: Car, Truck, Boat, Bicycle
To demonstrate inheritance in action, first, let us create a Vehicle class
class Vehicle {
protected String licensePlate = null;
public void setLicensePlate(String license) {
this.licensePlate = license;
}
}
In Java inheritance is declared using the extends keyword. We now extend the Vehicle class to have Car class:
class Car extends Vehicle {
protected int numberOfSeats = 0;
public int getNumberOfSeats() {
return this.numberOfSeats;
}
}
The protected Keyword
In addition to access modifiers public and private, protected access offers an intermediate level of access between them. Remember that a superclass’s private members are not accessible for other classes, including its subclasses. However, the protected members of a superclass are accessible from its subclasses. Yet, it is different from public members, which can be accessed by any class, regardless of the inheritance relationship. The public and protected members are similar in the fact that their original access modifiers are retained in the subclasses - public members of the superclass become public members of the subclass, and protected members of the superclass become protected members of the subclass.
Overriding Method and the super Keyword
In a subclass, Java allows the code to override (redefine) methods defined in the superclass. Using the super keyword a subclass can access the methods in its superclass. Here is an example of using the super keyword in a constructor and a method.
class Car extends Vehicle {
public Car(int i_NumberOfSeats) {
super();
//perform other initialization here
numberOfSeats = i_NumberOfSeats;
}
public void setLicensePlate(String license) {
super.setLicensePlate(license);
}
public String toString() {
return "The car has " + numberOfSeats + " seats. Its license is " + licensePlate;
}
}
The SportsCar class can be created by extending Car class
class SportsCar extends Car {
double maxSpeed = 0;
public SportsCar(int i_NumberOfSeats, double d_MaxSpeed) {
super(i_NumberOfSeats);
//perform other initialization here
maxSpeed = d_MaxSpeed;
}
}
When you override a method in a subclass, it is recommended to use @Override annotation. This way, if you misspell a method name or not correctly matching the parameters, you will be warned that your method does not actually override the intended methods as you think it does. Secondly, it makes your code easier to understand because it is more obvious about which methods are overwritten.
class SportsCar extends Car {
@Override
public void setLicensePlate(String license) {
this.licensePlate = license.toLowerCase();
}
@Override
public String toString() {
return supper.toString() + ". Its max speed is " + maxSpeed;
}
}
The final Keyword
The final keyword has different semantic depending on the context:
- A final class cannot be inherited. It is useful when there is a good reason to prohibit inheritance. Technically speaking, a developer marks a class as final to indicate that he has not considered or do not expect the class to be inherited.
- A final method cannot be overriden. The design does not expect the method to be changed even in its subclasses.
- A final variable can only be initialized once, making it safe to ensure the value cannot be changed once assigned.
A complete example
To complete this article, we will test how the objects of Car class and SportsCar class different in behavior.
Vehicle Class : Superclass
class Vehicle {
protected String licensePlate = null;
public void setLicensePlate(String license) {
this.licensePlate = license;
}
}
Car Class extending Vehicle
class Car extends Vehicle {
protected int numberOfSeats = 0;
public Car(int i_NumberOfSeats) {
super();
//perform other initialization here
numberOfSeats = i_NumberOfSeats;
}
public void setLicensePlate(String license) {
super.setLicensePlate(license);
}
public String toString() {
return "The car has " + numberOfSeats + " seats. Its license is " + licensePlate;
}
public int getNumberOfSeats() {
return this.numberOfSeats;
}
}
SportsCar Class extending Car Class
class SportsCar extends Car {
double maxSpeed = 0;
public SportsCar(int i_NumberOfSeats, double d_MaxSpeed) {
super(i_NumberOfSeats);
//perform other initialization here
maxSpeed = d_MaxSpeed;
}
@Override
public void setLicensePlate(String license) {
this.licensePlate = license.toLowerCase();
}
@Override
public String toString() {
return super.toString() + ". Its max speed is " + maxSpeed;
}
}
Main Test Method
//This class tests the above classes
public class VehiclesTest
{
public static void main(String args[])
{
Car personalCar = new Car(4);
personalCar.setLicensePlate("PERSONAL-BN123");
System.out.println(personalCar);
SportsCar sportsTeam = new SportsCar(2, 200);
sportsTeam.setLicensePlate("SPORTS-AB989");
System.out.println(sportsTeam);
}
}
Notice that the SportsCar has it's license lowercased and its toString() method appends the Car's toString() with its own max speed.
The above code produce:
The car has 4 seats. Its license is PERSONAL-BN123
The car has 2 seats. Its license is sports-ab989. Its max speed is 200.0
Summary
- Inheritance reduces development time through reusing of existing code base in a hierarchical manner.
- A superclass protected members have an intermediate level of protection between public and private access. They can be accessed by its subclasses.
- Java allows overriding methods of the superclass. We can use the super keyword to access the superclass methods.