Inheritance - Overriding MethodsS2C Home « Inheritance - Overriding Methods
In the Inheritance - Basics lesson we took a first look at the concept of inheritance and how in Java terminology, the general class that holds the group of common characteristics is known as the superclass and the specialised subset of this is known as the subclass. We then looked at how to achieve this hierarchial connection in Java using the extends
keyword,
wherein the subclass extends the superclass in the Inheritance - Using extends
lesson. We used this knowledge to create the Car
and Bus
subclasses.
By extending like this we have created an inheritance hierarchy where the subclass inherits the traits of the superclass, in other words the members of the superclass, assuming the access modifiers permit inheritance. Because the subclass is more specialised it can override the instance methods members of the superclass and also add new members of its own.
We used some new terminology there for members, did you notice? Yes we said override as opposed to overload, which we have already come across in the Objects & Classes section, in the Methods - Overloading & Varargs lesson. When we override the instance method members of the superclass in a subclass, we are writing a more specific method for use by the subclass that overrides the inherited method.
In this lesson we look at overriding a method where we create a new Truck
subclass and override the carry()
method from the Vehicle
superclass.
We do not override instance variables in a subclass with the same identifier in the superclass. This is known as hiding and will be discussed in the next lesson in Superclass Members.
We do not override static methods in a subclass with the same identifier in the superclass as these are class methods and not related to any instance. This is also known as hiding and will be discussed, paradoxically in the lesson on Polymorphism. Following is a slideshow to digest the information we have written so far about inheritance:
Overriding Methods Top
We just have one more subclass to code in our simple inheritance tree, the Truck
subclass. This class overrides the carry()
method from the Vehicle
superclass. This
is our first look at coding a method override and so we will just cover the basics and rules in this lesson. A method override must adhere to the contract it has with the superclass method. This contract
being, a method override must have exacly the same arguments and return type (or co-variant thereof) as the superclass method with the same method name. This is different to our examples of overloaded
methods in the Objects & Classes section, in the Methods lesson, in which the argument lists had to be different. In fact if you change
the argument lists, that's what you end up with an overloaded method. So to make sure we are doing a method override we need to keep the contract. Time to code up our Truck
subclass.
Our Truck
subclass Top
Here we code and test the Truck
subclass where we use the extends
keyword again to subclass the Vehicle
class. With the Truck
class we need to override
the carry()
method from the Vehicle
superclass. The superclass Vehicle
has the rest of the stuff we need.
package com.server2client;
/*
A Truck Class
*/
public class Truck extends Vehicle {
/*
Our carry() override method
*/
void carry(int tonnage) {
System.out.println("Our truck can carry up to " + tonnage + " tons of cargo.");
}
}
The above screenshot shows the output of compiling our Truck
subclass. We got a compiler error and the error message is quite informative for this one. So lets take a look at what happened:
package com.server2client;
/*
The carry() method in the Vehicle superclass
*/
public void carry(int carry) { ... } // We used the public
access modifier
/*
The override carry() method in the Truck subclass
*/
void carry(int tonnage) { ... } // We didn't put an access modifier on so its package-default
When we override a method, the overriding method can't be less accessible.
In our example it is so lets correct the override method and put the public
access modifier at the start of the carry()
method:
package com.server2client;
/*
A Truck Class
*/
public class Truck extends Vehicle {
/*
Our carry() override method
*/
public void carry(int tonnage) {
System.out.println("Our truck can carry up to " + tonnage + " tons of cargo.");
}
}
With the changes to the Truck
subclass it should fine fine now.
Lets test the new Truck
subclass to make sure it works:
package com.server2client;
/*
Test Class for Truck
*/
public class TestTruck {
public static void main (String[] args) {
Truck arctic = new Truck();
arctic.setChassis("3-axle chassis");
arctic.setMotor("12 stroke");
arctic.setWheels(12);
System.out.println("Our truck has a " + arctic.getChassis() + ", " + arctic.getMotor()
+ " motor and has " + arctic.getWheels() + " wheels.");
arctic.service(3);
arctic.carry(10);
arctic.load("trade goods.");
}
}
The above screenshot shows the output of testing our Truck
subclass. The class works as intended and uses the inherited members of the Vehicle
superclass, our carry()
method override to output some messages.
Overriding Method Rules Top
So when we override a superclass method there are some rules to adhere to:
- A method override must have exacly the same arguments as the superclass method with the same method name or you end up with an overloaded method.
- A method override must have the same return type (or co-variant thereof) as the superclass method with the same method name.
- When we override a method, the overriding method can't be less accessible, but can be more accessible.
- You cannot override a method marked with the
final
modifier. - You cannot override a method marked with the
private
access modifier. Even if you have a method in the subclass with the same method name and arguments as a private method in the superclass it knows nothing of that method as it can't see it and is just a normal non-overriding method - You cannot override a method marked with the
static
modifier as overridden methods pertain to instance methods and not the class. In fact if you use the same static method and parameters in a subclass as a static method in a superclass this is known as method hiding and is discussed in Static Overrides?.
There are other rules regarding exceptions declarations when using overrides and these are discussed in the Exceptions section when we look at Overridden Methods & Exceptions.
Hopefully you're getting a feel for how inheritance works now and how we can build up an inheritance heirarchy to avoid duplication and streamline more specific objects.
Preventing Inheritance/Overriding Top
There might be a scenario whereby, you need to stop a class from being inherited. We can stop inheritance occurring by using the final
keyword in the class definition:
package com.server2client;
/*
A final Class
*/
public final class A {
}
package com.server2client;
/*
B Class
*/
public class B extends A {
}
The above screenshot shows the result of trying to compile class B
.
On a similar note there might be a situation whereby, you need to stop a method from being overridden. We can stop this happening by using the final
keyword in the method definition:
package com.server2client;
/*
C Class
*/
public class C {
final void aMethod () {
System.out.println("Marked final so we can't override this method.");
}
}
package com.server2client;
/*
D Class
*/
public class D extends C {
void aMethod () {
System.out.println("This won't work.");
}
}
The above screenshot shows the result of trying to compile class B
.
- You can't mark abstract classes as
final
or you will get a compiler error. Abstract classes, by definition, need to be extended.
You can also use the final
keyword to create final local variables, final instance variables,
within parameter lists and for creating java constants.
Related Quiz
OO Concepts Quiz 5 - Inheritance - Overriding Methods
Lesson 5 Complete
In this lesson we continued our examination of inheritance by lookins at overriding methods and the rules associated with them.
What's Next?
We look further at inheritance and conceptualize where our objects fit into the hierarchy.