Java Inheritance
Java Inheritance
In Java, a class can inherit from another class. This is called extending a class. One class can extend another class. The two classes are called the superclass and the subclass. The subclass extends the superclass. Or, the subclass inherits from the superclass.
Inheritance Basics
When a class inherits from a superclass, it inherits parts of the superclass methods and fields. The subclass can also override (redefine) the inherited methods. Not the fields.
When a class inherits from a superclass, you can reference the class as either an instance of the subclass or superclass. I will get back to this later in this text.
In Java a class can only inherit from a single superclass. In some languages, like C++, it is possible for a subclass to inherit from multiple superclasses (multiple inheritance). Since multiple inheritance can create some weird problems, if e.g. the superclasses contain methods with the same names and parameters, multiple inheritance was left out in Java.
Inheritance can be an effective method to share code between classes that have some traits in common, and some parts which are different.
Here is diagram illustraing a class called
Vehicle
, which has two subclasses called Car
and Truck
.The class Car and Truck inherits from the class Vehicle. |
Declaration of Inheritance
You declare that one class extends another class by using the
extends
keyword in the class definition. Here is an example:public class Vehicle { protected String licensePlate = null; public void setLicensePlate(String license) { this.licensePlate = license; } }
public class Car extends Vehicle { protected String owner = null; public String getLicenseAndOwner() { return this.licensePlate + " : " + this.owner; } }
The
Car
class in this example extends the Vehicle
class.
Notice how the
Car
class can access the licensePlate
field in the Vehicle
class, from inside the method getLicenseAndOwner()
. Because the Car
class extends the Vehicle
class, thelicensePlate
field is now accessible inside a Car
instance. In other words, the Car
instance is also aVehicle
instance.References
In the example from the previous section you can reference an instance of the
Car
class, as an instance of the Vehicle
class. Because the Car
class extends (inherits from) the Vehicle
class, it is also said tobe a Vehicle
.
Here is a code example:
Car car = new Car(); car.setLicensePlate("1234XYZ"); String licenseAndOwner = car.getLicenseAndOwner(); Vehicle vehicle = car; vehicle.setLicensePlate("9999ABC");
First a
Car
instance is created. Then the methods setLicensePlate()
andgetLicenseAndOwner()
are called.
Second, the
Car
instance is assigned to a Vehicle
variable. Now the Vehicle
variable (reference) points to the Car
instance. After that, the setLicensePlate()
method is called. Notice, that since theVehicle
class does not have a getLicenseAndOwner()
method, you cannot call that method via theVehicle
reference, even if the object pointed to is really a Car
object.
As you can see, it is possible to use an instance of some subclass, as an instance of its superclass too. That way, you don't need to know exactly what subclass the object is an instance of. You could treat e.g. both
Truck
and Car
instances as Vehicle
instances.What is Inherited?
When a subclass extends a superclass, all protected and public fields and methods of the superclass can be accessed from the subclass. Fields and methods that have package scope access can be accessed by subclasses only if the subclass is located in the same package as the superclass. Private fields and methods of the superclass can never be referenced by subclasses.
Overriding Methods
In a subclass you can override (redefine) methods defined in the superclass. Here is an example:
public class Vehicle { String licensePlate = null; public void setLicensePlate(String licensePlate) { this.licensePlate = licensePlate; } }
public class Car extends Vehicle { public void setLicensePlate(String license) { this.licensePlate = license.toLowerCase(); } }
Notice how both the
Vehicle
class and the Car
class defines a method called setLicensePlate()
. Now, whenever the setLicensePlate()
method is called, it is the method defined in the subclass that is called. The method in the superclass is ignored.
To override a method, the method definition in the subclass must have exactly the same name and the same number of parameters, and the parameters must be listed in the exact same sequence as in the superclass. Otherwise the method in the subclass will be considered a separate method.
You cannot override private methods from a superclass. If the superclass calls a private method internally from some other method, it will continue to call that method from the superclass, even if you create a private method
Calling Superclass Methods
If you override a method in a subclass, but still need to call the method defined in the superclass, you can do so using the
super
reference, like this:public class Car extends Vehicle { public void setLicensePlate(String license) { super.setLicensePlate(license); } }
In the above code example the method
setLicensePlate()
in the Car
class, calls thesetLicensePlate()
method in the Vehicle
class.
You can call superclass implementations from any method in a subclass, like above. It does not have to be from the overridden method itself. For instance, you could also have called
super.setLicensePlate()
from a method in the Car
class called updateLicensePlate()
which does not override the setLicensePlate()
method.The @override Annotation
If you override a method in a subclass, and the method is all of a sudden removed or renamed or have its signature changed in the superclass, the method in the subclass no longer overrides the method in the superclass. But how do you know? It would be nice if the compiler could tell you that your overriding method no longer overrides a method in the superclass, right?
This is what the
@override
annotation above a method is used for. Here is an example:public class Car extends Vehicle { @Override public void setLicensePlate(String license) { this.licensePlate = license.toLowerCase(); } }
Fields
As mentioned earlier, fields cannot be overridden in a subclass. If you define a field in a subclass with the same name as a field in the superclass, the field in the subclass will hide the field in the superclass. If the subclass tries to access the field, it will access the field in the subclass.
If, however, the subclass calls up into a method in the superclass, and that method accesses the field with the same name as in the subclass, it is the field in the superclass that is accessed.
Here is an example:
public class Vehicle { String licensePlate = null; public void setLicensePlate(String licensePlate) { this.licensePlate = licensePlate; } public String getLicensePlate() { return licensePlate; } }
public class Car extends Vehicle { protected String licensePlate = null; @Override public void setLicensePlate(String license) { super.setLicensePlate(license); } @Override public String getLicensePlate() { return super.getLicensePlate(); } public void updateLicensePlate(String license){ this.licensePlate = license; } }
Notice how both classes have a
licensePlate
field defined.
Both the
Vehicle
class and Car
class has the methods setLicensePlate()
andgetLicensePlate()
. The methods in the Car
class calls the corresponding methods in the Vehicle
class. The result is, that eventually both set of methods access the licensePlate
field in the Vehicle
class.
The
updateLicensePlate()
method in the Car
class however, accesses the licensePlate
field directly. Thus, it accesses the licensePlate
field of the Car
class. Therefore, you will not get the same result if you call setLicensePlate()
as when you call the updateLicense()
method.
Look at the following lines of code:
Car car = new Car(); car.setLicensePlate("123"); car.updateLicensePlate("abc"); System.out.println("license plate: " + car.getLicensePlate());
This code will print out the text
123
.
The
updateLicensePlate()
method sets the license plate value on the licensePlate
field in theCar
class. The getLicensePlate()
method, however, returns the value of the licensePlate
field in the Vehicle
class. Therefore, the value 123
which is set as value for the licensePlate
field in theVehicle
class via the setLicensePlate()
method, is what is printed out.
0 comments: