Hierarchies for Inheritance#
Consider our example from the last chapter, where we created the class Square
. Suppose now we add the class Rectangle
, which we characterize with the data attributes length
and width
and also include the methods calcArea
and calcPerimeter
. We might make a file such as this one on the left (remembering our file for Squares, shown on the right):
There is a lot of repetition in the code above. Really, a square is just a special kind of rectangle, so if we were to set the width of a square equal to its length (by adding that instance variable), then the methods for calculating area and perimeter could be identical. Could we avoid repeating their code inside the Square
class? The answer is “yes.” As proficient Computing Scientists, we want to have a shorter amount of code where possible – less code to read as we continue developing our project.
Factoring into Superclass#
The idea of a square being a special kind of rectangle is handled in Java by creating a hierarchy, using the Java reserved word extends
. We want to create a picture as follows, where part a) shows the simplistic hierarchy and part b) shows the hierarchy with the data fields and methods:
a. Collapsed |
b. Expanded |
This picture shows that a square is a special kind of a rectangle, that is, a square is a specialization of a rectangle. A square inherits attributes from a rectangle, and not the other way around. In the diagram, the arrow shows the path from Square
to Rectangle
. If we have a square we can move upwards to find attributes in a rectangle that may apply. We cannot move downward from a rectangle into a square. A rectangle is more general than a square and cannot be inherited from a square because assuming equal length and width will not work for some rectangles. We say that Rectangle
is a superclass of Square
. Alternatively, Square
is a subclass of Rectangle
.
Here is the new Java code creating the hierarchical relationship between a rectangle and a square, and factoring the code so that calcArea
and calcPerimeter
are only in one place, namely inside the class Rectangle
:
See how short our class Square
has become. Objects of type square will inherit the data fields (length
and width
) from rectangles and also the methods to find area and perimeter. Note though that it is important to create a constructor for squares, which calls the constructor of a rectangle (by the use of the super
method and not by the usual constructor name). This constructor ensures that length and width are set to the same value. When we run the main
program we created in the multiple files section of Chapter 2, the results are identical even though our file structure now includes inheritance.
Short Code is (Often) Better
The most important thing in writing code is correctness. After that, there are other characteristics of code that are important. One is readability, and shorter code is usually easier to read.
The access modifiers on length
and width
have been changed to protected
, to allow the code in Square
to have direct access to them. In the code written so far, we could have left that access private
(since we have never directly accessed length
or width
inside the class for Square
), but coming up we will use protected
access.
Let’s look at these lines of code again, where a Square
is created and then used:
Square mirror = new Square(5);
System.out.println("mirror area: " + mirror.calcArea());
During execution, when the object mirror
is made, the constructor for a Square
is called. This constructor, in turn, calls the constructor of the superclass, that is, the constructor of the class for Rectangle
. This constructor is called with the length
of the square becoming both the length
and width
of the rectangle. Hence an object, an instance of Square
, with size 5 X 5 is created in memory. The name of this object is mirror
.
In the print statement, the dot message calcArea()
is sent to mirror
. The computer first looks at the level of a Square
, since mirror
is a Square
, but no such method is found. This means that the hierarchy must be used. Moving up one level, the calcArea()
method is found, in class Rectangle
. This method is now run to produce our result of \(25.0\).
Practice Questions#
Create a way to determine the length of the diagonal of a square and of a rectangle.
Create a new
Square
of size 8 X 8 and print the length of its diagonal.Create a new
Rectangle
of size 5 X 3 and print the length of its diagonal.