Hi! In previous lessons, we've already briefly become acquainted with the concept of inheritance.
Today, we'll touch on this topic again, but again not too deeply. We are still going to have a more detailed lesson on this in the future. Today we'll just take a quick look at a few practical examples and get acquainted with an interesting operator in Java.
Inheritance
So, what is inheritance? Inheritance is a programming mechanism (including in Java) that lets you declare a new class based on an existing one. The derived class then gains access to the fields and methods of the parent class. Why would we need this? Well, imagine that you need to create several car classes in a program: Truck, RaceCar, Sedan, Pickup, etc. Even before writing any code, you know for sure that all these classes have a lot in common: all cars have a model name, year of manufacture, engine size, maximum speed, etc. (not to mention the fact that they all have wheels and other parts in common). In this situation, you can:- Create these fields in each class (adding them to each new car class as you create it)
- Bring the fields common to all cars into a
Car
parent class, and then use the keyword extends to derive all classes for specific types of cars from theCar
class.
public class Car {
private String model;
private int maxSpeed;
private int yearOfManufacture;
public Car(String model, int maxSpeed, int yearOfManufacture) {
this.model = model;
this.maxSpeed = maxSpeed;
this.yearOfManufacture = yearOfManufacture;
}
}
public class Truck extends Car {
public Truck(String model, int maxSpeed, int yearOfManufacture) {
super(model, maxSpeed, yearOfManufacture);
}
}
public class Sedan extends Car {
public Sedan(String model, int maxSpeed, int yearOfManufacture) {
super(model, maxSpeed, yearOfManufacture);
}
}
At a minimum, we avoid the unnecessary duplication of code (and we should always strive for that when writing programs).
Plus, we have a simple and understandable class structure, with all fields common to all cars consolidated into one class.
If trucks have any special fields that other cars do not, they can be declared in the Truck
class.
The same goes for methods. All cars have certain common behavior that can be described with methods, e.g. start the car, accelerate/brake, etc.
These common methods can be consolidated into the Car
parent class, and each specific type of car can define its unique actions in their derived classes.
public class Car {
public void gas() {
// Accelerate
}
public void brake() {
// Brake
}
}
public class F1Car extends Car {
public void pitStop() {
// Only race cars make pit stops
}
public static void main(String[] args) {
F1Car formula1Car = new F1Car();
formula1Car.gas();
formula1Car.pitStop();
formula1Car.brake();
}
}
We added the methods common to all cars to the Car
class. But, look at the F1Car
class, which represents "Formula 1" race cars. Pit stops (stops for urgent car maintenance) are only done in races, so we added this specific functionality to the relevant derived class.
instanceof operator
In Java, there is a special operator, instanceof, for checking to see if an object was created based on a particular class. It returns true or false depending on the result of the check. Let's see how it works using the classes in our car example:
public class Truck extends Car {
public static void main(String[] args) {
Truck truck = new Truck();
System.out.println(truck instanceof Car);
}
}
Output:
true
The instanceof
operator returns true, since we have a Truck
object, and all trucks are cars. The Truck
class is derived from the Car
class. All trucks are created based on the common parent, the Car
class.
Look closely at how the instanceof
operator is used. You write it without a period, since it's an operator, not a method ("object instanceof Class”).
Let's try another way:
public static void main(String[] args) {
Car car = new Car();
System.out.println(car instanceof Truck);
}
Output:
false
The Car
class (and car objects) does not derive from the Truck
class. All trucks are cars, but not all cars are trucks. Car
objects are not based on the Truck
class.
One more example:
public static void main(String[] args) {
Car car = new Car();
Truck truck = new Truck();
System.out.println(car instanceof Object && truck instanceof Object);
}
Output:
True
Here the logic is simple too: all classes in Java, including classes you create, descend from the Object
class (even though you don't write "extends Object"—it's already implied).
How and when would this be useful?
The instanceof
operator is most commonly used when overriding the equals()
method.
For example, here's how the equals
method is implemented in the String
class:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
Before comparing a String
to the passed object, the method tests to see whether the object is even a string?
Only then does it start comparing the two objects' properties.
If this test didn't exist, any object with value and length fields could be passed to the method and compared with a String, which would be wrong, of course.
GO TO FULL VERSION