7.6. Method Overrides¶
It is common for a child class to change a behavior (method) inherited from a parent. In Java, this is called a method override.
Method overrides can occur in two ways:
The child changes the code in the inherited method without using any of the code in the parent’s method (Example 1 below).
The child adds to the code it inherited from the parent. Here, the inherited code in the method is still used. (Example 2 below).
Example 1 - Overwriting all Inherited Code
The video below illustrates how to override an inherited method. The
starter code for the example in the video can be found under the
person
subdirectory of the cs1302-inheritance
directory you
downloaded at the beginning of this tutorial. For convenience, we have
included the UML Class Diagram for the code we created in the earlier
section below (dropdown to view):
UML Class Diagram for the Person Example (from earlier section)
Follow along with this video using the code you modified earlier in the chapter:
Important
If a method is overridden in a child class, the method closest to the type of the object will be called when the code is run.
Learn by Experimenting!
You may have noticed the @Override
above each toString()
method. This is an example of an annotation. In Java,
annotations are used to provide extra information to the compiler. In
this case, the @Override
is an optional annotation that lets the
compiler know your intent is to override. Try the following scenarios:
Omit the
@Override
, then recompile.Omit the
@Override
and misspell thetoString
method name, then recompile.- Include the
@Override
and misspell thetoString
method name, then recompile.
- Include the
Notice the error that occurs in the third situation that did not occur
in the second. This is the primary purpose of the annotation. Although
optional, it allowed you to tell the compiler that your intent is to
override. If the compiler sees the @Override
annotation, then it
checks to make sure it’s an override and will let you know if you made a
mistake!
Example 2 - Adding to Inherited Code
It is also possible to have the child class build on the action performed
in the parent class. In other words, the child can perform the same action
as the parent and then do additional actions in the overridden method.
In these scenarios, it is important to avoid redundant code and simply call
the parent’s version of the method using super
.
Let’s add a few methods (and a Cat
class) to our animal hierarchy from the
previous section. Take a moment to review the updated UML Class Diagram below
(Driver
class omitted to save space):
Notice that both Cat
and Dog
override the method describe
from
the parent class. Now, let’s consider the following implementation for
the describe
method in the Animal
class:
/**
* Prints a description of the {@Animal}.
*/
public void describe() {
System.out.println("This is an animal named " + this.name + ".");
} // describe
From within the Animal
class, the description has to be a bit vague since
we are talking about a generic animal. However, as we move down the
hierarchy (overriding the describe
method as we go), the child classes
can add to the parent’s output to print a more accurate description.
The implementation of describe
in the Cat
class could leverage
the work that’s already done in the parent (Animal
) class without
needing to repeat the code:
/**
* Prints a description of the {@Cat}.
*/
@Override
public void describe() {
super.describe(); // calls the describe method of the parent.
System.out.println(this.getName() + " is an agile cat."); // adds to it
} // describe
Test Yourself
What do you expect would be output after running the main
method
below? Assume that the method has access to both the Animal
and
Cat
classes above.
Notice that the data types of the variables are not the same.
public static void main(String[] args) {
// 1.
Cat cat = new Cat("Whiskers");
System.out.println("\nCat:");
cat.describe();
// 2.
Animal cat2 = new Cat("Garfield");
System.out.println("\nCat:");
cat2.describe();
} // main
Test Yourself Solution (open after attempting the question above)
The output from the above code should be:
Cat:
There is an animal named Whiskers.
Whiskers is an agile cat.
Cat:
There is an animal named Garfield.
Garfield is an agile cat.
Note that both examples call the describe
method in the Cat
class
because both are objects of type Cat
. Also, when we call the describe
method in the Cat
class, we first see the output written in the Animal
class because we call the parent’s method using super
.