Consider a world in which there are just two types of object, namely circles and squares. We can think of this as a world of shapes. The idea of shape, however, is abstract. We cannot instantiate a bare shape; we can only instantiate a specific shape, either a circle or a square. Both circles and squares, however, are instances of shapes. For example we can ask for the area of a shape, whether it is a circle or a square. The shape class is thus the union of the circle and square classes.
Java deals with situations like this by using the notion of an abstract class, which can be defined as follows.
public abstract class Shape {
public abstract double area();
}
For simplicity the Shape class provides just the single
area method. The concrete Circle and
Square classes are now defined as extensions of the
Shape class.
public class Circle extends Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
public double area() {
return Math.PI * radius * radius;
}
}
and
public class Square extends Shape {
private double side;
public Square(double side) {
this.side = side;
}
public double area() {
return side * side;
}
}
Both sub-classes provide constructors, which take as argument the
critical dimension. Note that because the Circle and Square classes both extend the Shape class, any
instance of a circle or a square is in fact an instance of a shape,
and hence a legitimate value for a variable of Shape type.
A simple application would be as follows:
Shape s1 = new Circle(1.0); Shape s2 = new Square(1.0); System.out.println(s1.area()); System.out.println(s2.area());Both s1 and s2 are declared to be of type Shape, rather than of the more specific Circle or Square types. At run-time, however, s1 and s2 will know themselves to be of one or other of the more specific types, because of the way they have been constructed, so that it is known which area method to call.