## CS 1713-001 Introduction to Computer Science Spring 2001 -- Shapes and PolymorphismSolution to the Exercise of adding two new shapes: Rectangle and RectangularSolid

This review exercise asks you to add two new classes to an existing hierarcy. This is the same as a previous example. It has classes Shape, Point, Circle, and Cylinder. You are to write code for two new shapes:
• Rectangle: Extends Point and adds data fields length, and width. Redefines methods toString, getName, and area. The method getName should return "Rectangle" unless length == width, in which case it should return "Square".
• RectangularSolid: Extends Rectangle and adds data field height. Redefines methods area, volume, toString, and getName. In case length == width and length == height, getName should return "Cube".

Then test class for the example creates an array of 15 shapes, including 3 of each type, and then sorts it into order, using the names of each type of shape as the primary sort criterion, and if the names are the same, using the ID number. (Here the solution, consisting just of definitions for the classes Rectangle and RectangularSolid, is highlighted in boldface.)

```// Shape.java: abstract base class
public abstract class Shape { // abstract class, can't instantiate
// to implement an idNumber
private static int counter = 0;
private int idNumber;
public Shape () {
idNumber = ++counter;
}
public int getIdNumber() { return idNumber;}

public double area() { return 0.0; }
public double volume() { return 0.0; }
public abstract String getName(); // abstract, so omit body
}

// Point.java: the class Point
public class Point extends Shape {
protected int x, y; // coordinates of the Point

// constructor
public Point( int a, int b ) { x = a; y = b; }

// get x coordinate
public int getX() { return x; }

// get y coordinate
public int getY() { return y; }

// convert the point into a String representation
public String toString()
{ return "[" + x + ", " + y + "]"; }

// return the class name
public String getName() { return "Point"; }
}

// circle.java: the class Circle
public class Circle extends Point {  // inherits from Point

// Constructor
public Circle( double r, int a, int b ) {
super( a, b );  // call the superclass constructor
radius = ( r >= 0 ? r : 0 );
}

// Calculate area of Circle

// convert the Circle to a String
public String toString()
{ return "Center = " + super.toString() +

// return the class name
public String getName() { return "Circle"; }
}

// Cylinder.java: the class Cylinder
public class Cylinder extends Circle {
protected double height;  // height of Cylinder

// constructor
public Cylinder( double h, double r, int a, int b ) {
super( r, a, b );   // call superclass constructor
height = ( h >= 0 ? h : 0 );
}

// Calculate area of Cylinder (i.e., surface area)
public double area() {
return 2 * super.area() +
2 * Math.PI * radius * height;
}

// Calculate volume of Cylinder
public double volume() { return super.area() * height; }

// Convert a Cylinder to a String
public String toString() {
return super.toString() + "; Height = " + height;
}

// Return the class name
public String getName() { return "Cylinder"; }
}

// Rectangle.java: the class Rectangle
public class Rectangle extends Point {  // inherits from Point
protected double length;
protected double width;

// Constructor
public Rectangle( double len, double wid, int a, int b ) {
super( a, b );  // call the superclass constructor
length = ( len >= 0 ? len : 0 );
width  = ( wid >= 0 ? wid : 0 );
}

// Calculate area of Rectangle
public double area() { return length * width; }

// convert the Rectangle to a String
public String toString() {
return "Center = " + super.toString() +
"; Length = " + length + ", Width = " + width; }

// return the class name
public String getName() {
if (length == width) return "Square";
else return "Rectangle";
}
}

// RectangularSolid.java: the class RectangularSolid
public class RectangularSolid extends Rectangle {
protected double height;  // height of RectangularSolid

// constructor
public RectangularSolid(double h, double len, double wid, int a, int b) {
super(len, wid, a, b);   // call superclass constructor
height = ( h >= 0 ? h : 0 );
}

// Calculate area of RectangularSolid (i.e., surface area)
public double area() {
return 2 * super.area() +
2 * length * height +
2 * width * height;
}

// Calculate volume of RectangularSolid
public double volume() { return super.area() * height; }

// Convert a RectangularSolid to a String
public String toString() {
return super.toString() + "; Height = " + height;
}

// Return the class name
public String getName() {
if (length == width && length == height)
return("Cube");
else return "RectangularSolid";
}
}

// ShapeTest.java: test point, circle, cylinder hierarchy
public class ShapeTest {

private Shape shapes[];

public void createShapes() {

shapes = new Shape[15]; // generic array of any shape

shapes[0]  = new Rectangle(3.0, 4.0, 6, 8);
shapes[1]  = new Point(7, 11);
shapes[2]  = new Circle(3.5, 22, 8);
shapes[3]  = new Cylinder(10, 3.3, 10, 10);
shapes[4]  = new RectangularSolid(2.0, 3.0, 4.0, 6, 8);
shapes[5]  = new Point(8, 12);
shapes[6]  = new Rectangle(2.0, 2.0, 7, 9);
shapes[7]  = new Circle(3.6, 23, 9);
shapes[8]  = new Cylinder(12, 3.4, 20, 20);
shapes[9]  = new Rectangle(6.0, 6.0, 5, 7);
shapes[10] = new RectangularSolid(3.0, 3.0, 3.0, 10, 4);
shapes[11] = new Point(9, 13);
shapes[12] = new Circle(3.7, 24, 10);
shapes[13] = new Cylinder(14, 3.5, 30, 30);
shapes[14] = new RectangularSolid(4.0, 4.0, 4.0, 8, 9);
}

public void printShapes() {

// Loop through arrayOfShapes. Use polymorphism to print the name,
// area, and volume of each object.
System.out.println("PRINT THE SHAPES AS AN ARRAY OF SHAPE");
for ( int i = 0; i < shapes.length; i++ ) {
System.out.println(shapes[i].getName() + ": " +
shapes[i].toString() + ", ID: " +
shapes[i].getIdNumber());
System.out.println("Area = " + shapes[i].area());
System.out.println("Volume = " + shapes[i].volume());
System.out.println();
}
}

//  insertionSort: Sorts array of Shapes using the insertion sort
public void insertionSort () {
for (int index = 1; index < shapes.length; index++) {
Shape key = shapes[index];
int position = index;
// shift larger values to the right
while (position > 0 && compareShapes(shapes[position-1], key) > 0) {
shapes[position] = shapes[position-1];
position--;
}
shapes[position] = key;
}
}

private int compareShapes (Shape s1, Shape s2) {
if ((s1.getName()).equals(s2.getName()))
return s1.getIdNumber() - s2.getIdNumber();
else return (s1.getName()).compareTo(s2.getName());
}

public static void main (String[] args) {
ShapeTest shapeTest = new ShapeTest();
shapeTest.createShapes();
shapeTest.insertionSort();
shapeTest.printShapes();
}
}
```
Here is the output that my own program produced:
```
PRINT THE SHAPES AS AN ARRAY OF SHAPE
Circle: Center = [22, 8]; Radius = 3.5, ID: 3
Area = 38.48451000647496
Volume = 0.0

Circle: Center = [23, 9]; Radius = 3.6, ID: 8
Area = 40.71504079052372
Volume = 0.0

Circle: Center = [24, 10]; Radius = 3.7, ID: 13
Area = 43.00840342764427
Volume = 0.0

Cube: Center = [10, 4]; Length = 3.0, Width = 3.0; Height = 3.0, ID: 11
Area = 54.0
Volume = 27.0

Cube: Center = [8, 9]; Length = 4.0, Width = 4.0; Height = 4.0, ID: 15
Area = 96.0
Volume = 64.0

Cylinder: Center = [10, 10]; Radius = 3.3; Height = 10.0, ID: 4
Area = 275.76900313211206
Volume = 342.11943997592846

Cylinder: Center = [20, 20]; Radius = 3.4; Height = 12.0, ID: 9
Area = 328.9875826839231
Volume = 435.8017329059761

Cylinder: Center = [30, 30]; Radius = 3.5; Height = 14.0, ID: 14
Area = 384.84510006474966
Volume = 538.7831400906495

Point: [7, 11], ID: 2
Area = 0.0
Volume = 0.0

Point: [8, 12], ID: 6
Area = 0.0
Volume = 0.0

Point: [9, 13], ID: 12
Area = 0.0
Volume = 0.0

Rectangle: Center = [6, 8]; Length = 3.0, Width = 4.0, ID: 1
Area = 12.0
Volume = 0.0

RectangularSolid: Center = [6, 8]; Length = 3.0, Width = 4.0; Height = 2.0, ID: 5
Area = 52.0
Volume = 24.0

Square: Center = [7, 9]; Length = 2.0, Width = 2.0, ID: 7
Area = 4.0
Volume = 0.0

Square: Center = [5, 7]; Length = 6.0, Width = 6.0, ID: 10
Area = 36.0
Volume = 0.0
```