Note A.4.4.
If you look closely at the UML diagram in Figure A.4.1, you will see that the class name and the two method names are in italics. This is how you signify an abstract entity in UML.
Shape
class is the parent of the Rectangle
and Circle
child classes.Shape
, Rectangle
, and Circle
classesShape
has an x and y location on the screen, you can calculate its area and perimeter, and you can use toString
to convert it to a string. Let’s start writing the code for this class.public class Shape {
private double x;
private double y;
public Shape(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() {
return this.x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return this.y;
}
public void setY(double y) {
this.y = y;
}
public double calcArea() {
// ?????
}
public double calcPerimeter() {
// ?????
}
public String toString() {
return String.format("(%.1f, %.1f)", this.x, this.y);
}
}
calcArea
and calcPerimeter
methods. How do we calculate the area and perimeter of a “shape”? We don’t have that sort of problem with circles and rectangles. We know the formulas for calculating their area and perimeter (AKA circumference). But a “shape” really doesn’t exist. If I tell you to draw me a shape, you’ll ask me “which one?” Shapes are an abstraction.abstract
on the class declaration. This tells Java that we will never directly instantiate a Shape
object. If anyone tries something like the following, they will get an error message.Shape myShape = new Shape(3.0, 4.5);
abstract
on the declarations of calcArea
and calcPerimeter
. And, most important, we will provide only the method header—there will be no method body. Listing A.4.3 shows the changed lines:public abstract class Shape {
private double x;
private double y;
// ...
public abstract double calcArea();
public abstract double calcPerimeter();
public String toString() {
return String.format("(%.1f, %.1f)", this.x, this.y);
}
}
Circle
class, which extends Shape
. This is not an abstract class—we know how to calculate a circle’s area and perimeter (circumference):public class Circle extends Shape {
private double radius;
public Circle(double x, double y, double radius) {
super(x, y);
this.radius = radius;
}
public double getRadius() {
return this.radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
public double calcArea() {
return Math.PI * this.radius * this.radius;
}
public double calcPerimeter() {
return 2.0 * Math.PI * this.radius;
}
public double calcCircumference() {
return calcPerimeter();
}
public String toString() {
return String.format("Circle: %s [radius %.1f]", super.toString(),
this.radius);
}
}
Circle
Classsuper
keyword to call methods in the parent class. Because Shape
never defined the body of the calcArea
and calcPerimeter
methods, the Circle
class must override the methods and provide a method body (lines 17–23). If we omit a definition for calcArea
, we get this error:Circle.java:1: error: Circle is not abstract and does not override abstract method calcArea() in Shape public class Circle extends Shape { ^ 1 error
Shape
, you can use polymorphism to create, for example, an array of Shape
and assign concrete (non-abstract) objects such as Circle
and Rectangle
to its elements, as in Listing A.4.7.public class ShapeExample {
public static void main(String[] args) {
Shape[] shapeList = {
new Circle(3.0, 4.0, 1.5),
new Rectangle(1.5, 2.5, 4.7, 8.3)
};
for (Shape s: shapeList) {
System.out.printf("%s area: %.2f perimeter: %.2f%n",
s, s.calcArea(), s.calcPerimeter());
}
}
}
Bicycle
, ElectricBicycle
, and CargoBicycle
classes from Exercise A.3.1.Bicycle
, ElectricBicycle
, and CargoBicycle
public class ElectricCargoBicycle extends ElectricBicycle, CargoBicycle { // ... }
ElectricCargoBicycle
Electrified
interface:interface Electrified {
public int getChargeCapacity();
public double getCurrentCharge();
public void setCurrentCharge(double charge);
}
Bicycle
class in Listing A.4.11:class Bicycle {
private double frameSize;
private int nGears;
private int currentGear;
Bicycle(double frameSize, int nGears) {
this.frameSize = frameSize;
this.nGears = nGears;
setCurrentGear(nGears);
}
public double getFrameSize() {
return this.frameSize;
}
public int getNGears() {
return nGears;
}
public int getCurrentGear() {
return currentGear;
}
public void setCurrentGear(int currentGear) {
this.currentGear = Math.min(this.nGears, Math.max(currentGear, 1));
}
}
ElectricBicycle
class lookss like this:class ElectricBicycle extends Bicycle implements Electrified {
private int chargeCapacity;
private double currentCharge;
ElectricBicycle(double frameSize, int nGears, int chargeCapacity) {
super(frameSize, nGears);
this.chargeCapacity = chargeCapacity;
}
/* Implement the methods in the interface */
public int getChargeCapacity() {
return this.chargeCapacity;
}
public double getCurrentCharge() {
return this.currentCharge;
}
public void setCurrentCharge(double charge) {
this.currentCharge = Math.max(0, Math.min(charge, chargeCapacity));
}
}
implements
the interface. Because this class implements Electrified
, it must provide method bodies for all the methods defined in the interface; those are in lines 11–21.ElectricCargoBicycle
by using an interface. We extend CargoBicycle
and implement Electrified
:class ElectricCargoBicycle extends CargoBicycle implements Electrified {
private int chargeCapacity;
private double currentCharge;
public ElectricCargoBicycle(double frameSize, int nGears,
double maxLoad, int chargeCapacity) {
super(frameSize, nGears, maxLoad);
this.chargeCapacity = chargeCapacity;
this.currentCharge = 0.0;
}
/* Implement the methods in the interface */
public int getChargeCapacity() {
return this.chargeCapacity;
}
public double getCurrentCharge() {
return this.currentCharge;
}
public void setCurrentCharge(double charge) {
this.currentCharge = Math.max(0, Math.min(charge, chargeCapacity));
}
}
Bicycle
and its SubclassesBattery
class and put one of those objects into the electric bicycle and electric cargo bicycle classes.ArrayList
class implements these interfaces:Iterable
, which provides methods for enabling iteration via enhanced for
loopsCollection
, which provides methods for adding and removing elementsList
, which provides methods for integer indexing