Java Reference
In-Depth Information
// Print details
System.out.println("Name: " + name);
System.out.println("Area: " + area);
System.out.println("Perimeter: " + perimeter);
}
}
}
The
ShapeUtil
class contains two
static
methods:
drawShapes()
and
printShapeDetails()
. Both accept an array
of
Shape
objects as a parameter. The
drawShapes()
method draws all the shapes by calling the
draw()
method of each
element in the array passed to it. The
printShapeDetails()
method prints details,
name
,
area
, and
perimeter
of the
shapes passed to it. The beauty of the code in the
ShapeUtil
class is that it never refers to any subclasses of the
Shape
class.
It has no knowledge about the
Rectangle
or
Circle
class at all. It does not even care if a
Rectangle
class or a
Circle
class
exists, although the code will work with
Rectangles
,
Circles
, and objects of any descendants of the
Shape
class. You may
argue that you could have written the same code even if you did not declare the
Shape
class as
abstract
. So, what is the big
deal about declaring the
Shape
class as
abstract
? You are getting two advantages by declaring the
Shape
class as
abstract
:
If you did not declare the
•
Shape
class
abstract
, you were forced to provide implementations
for the three
abstract
methods in the class. Since the
Shape
class does not know what shape
object it will take the form of, it is not appropriate for it to provide implementations for these
methods. For now, let's assume that you can handle this issue by providing an empty body for
the
draw()
method and returning zero (or maybe a negative number) from the
getArea()
and
getPerimeter()
methods in the
Shape
class. Let's move to the next advantage, which is more
compelling.
•
You are forced to declare the
Shape
class as
abstract
because you had declared three
abstract
methods in it. The greatest advantage of declaring an
abstract
method in a class is
to force its subclasses to override and provide implementation for it. The
abstract
methods
in the
Shape
class forced the
Rectangle
and
Circle
subclasses to override them and provide
implementations for them. Was it not what you wanted?
Listing 16-40 has code that tests the
ShapeUtil
class along with the
Shape
,
Rectangle
, and
Circle
classes. It
creates an array of
Shape objects
. It populates one element of the array with a
Rectangle
and another with a
Circle
.
It passes the array to the
drawShapes()
and
printShapeDetails()
methods of the
ShapeUtil
class, which draws the
shapes and prints their details according to the type of objects placed in the array.
Listing 16-40.
A Test Class to Test Shape, Rectangle, Circle, and the ShapeUtil Class
// ShapeUtilTest
package com.jdojo.inheritance;
public class ShapeUtilTest {
public static void main(String[] args) {
// Create some shapes, draw, and print their details
Shape[] shapeList = new Shape[2];
shapeList[0] = new Rectangle(2.0, 4.0); // Upcasting
shapeList[1] = new Circle(5.0); // Upcasting
// Draw all shapes
ShapeUtil.drawShapes(shapeList);
// Print details of all shapes
ShapeUtil.printShapeDetails(shapeList);
}
}