Abstract methods

Figure 472. Calculating a shape's area Slide presentation Create comment in forum
public class Rectangle extents Shape {
  /**
   * Calculate the area.
   * @return The rectangle's area
   */
  public double getArea() {
    return width * height;
  }
public class Circle extents Shape {
  /**
   * Calculate the area.
   * @return The circle's area
   */
  public double getArea() {
    return Math.PI * radius * radius;
  }

Figure 473. Desired: Polymorphic getArea() call Slide presentation Create comment in forum
final Shape[] shapes  = {
    new Circle(1, 1, 2.) ,
    new Rectangle(1, -1, 2., 3.)};

for (final Shape s : shapes) {
  System.out.println(s.toString() + ": area = " + s.getArea()); 
}
Circle at (1.0|1.0), radius= 2.0: area = 12.566370614359172
Rectangle at (1.0|-1.0), width= 2.0, height=3.0: area = 6.0

An array of Shape references.

A Rectangle is a Shape and likewise is Circle. We can thus assign both Circle and Rectangle instances to variables (or array elements) of type Shape by means of upcasting.

Polymorphic dispatch: Depending on the object's type the Java runtime will automatically choose either Rectangle.toString()/ Rectangle.getArea() or Circle.getArea() / Circle.toString()/ Circle.getArea() respectively.


Figure 474. Problems: Slide presentation Create comment in forum
  • No meaningful getArea() method in class Shape possible.

  • Meaningful implementations exist both in subclass Rectangle and Circle.

Solution: Abstract method getArea() in superclass Shape.


Figure 475. abstract method getArea() Slide presentation Create comment in forum
abstract public class Shape {
  /**
   * Calculate the shape's area.
   * @return The shape's area
   */
  abstract public double getArea(); ...
public class Rectangle extends Shape {
  @Override
  public double getArea() {
    return width * height;
  }...
public class Circle ... {
 @Override
  public double getArea() {
    return Math.PI *
           radius * radius;
  } ...

Superclass Shape contains an abstract method and must thus itself be declared abstract as well.

Note

You cannot create instances of abstract classes. You may however create instances of derived non-abstract classes.

Method getArea() cannot be implemented in a meaningful way. Its abstract modifier is a promise that some concrete (= non-abstract) subclass will either offer an implementation of getArea() or will have an intermediate parent class doing so.

In other words: The abstract keyword requires a corresponding implementation in some derived non-abstract subclass.

An abstract method must not have an implementing body {...}.

Both Rectangle and Circle are concrete (=non-abstract) classes and are thus obliged to provide an implementation of double getArea().


Figure 476. abstract method getArea() Slide presentation Create comment in forum

Figure 477. What's a shape anyway? Slide presentation Create comment in forum
What's a “shape” anyway?

Figure 478. No instances of abstract classes. Slide presentation Create comment in forum
final Shape s =
   new Shape(1., 2.); // 'Shape' is abstract; cannot be instantiated

Figure 479. Mandatory getArea() implementation. Slide presentation Create comment in forum
// Error: Class 'Circle' must either be declared abstract or
//        implement abstract method 'getArea()' in 'Shape'
public class Circle extends Shape {

  public Circle(double x,double y, double radius) {
    super(x, y);
    this.radius = radius;
  }
  private double radius;
}

Figure 480. Facts about abstract fields, methods and classes. Slide presentation Create comment in forum
  • A class containing an abstract method must itself be declared abstract.

  • abstract classes are allowed to host non-abstract methods.

  • A class may be declared abstract irrespective of purely containing non-abstract methods.