Effective Java 20 Prefer class hierarchies to tagged classes

时间:2023-03-09 13:17:48
Effective Java 20 Prefer class hierarchies to tagged classes

Disadvantage of tagged classes

1. Verbose (each instance has unnecessary irrelevant fields).

2. Error-prone (Program will fail by initializing wrong fields).

3. Inefficient (Memory footprint is increased for not used field).

/**

* Tagged class - vastly inferior to a class hierarchy!

* @author Kaibo

*/

class Figure {

enum Shape {

RECTANGLE, CIRCLE

     };

// Tag field - the shape of this figure

final Shape shape;

// These fields are used only if shape is RECTANGLE

double length;

double width;

// This field is used only if shape is CIRCLE

    double radius;

// Constructor for circle

Figure(double radius) {

shape = Shape.CIRCLE;

this.radius = radius;

}

// Constructor for rectangle

Figure(double length, double width) {

shape = Shape.RECTANGLE;

this.length = length;

this.width = width;

}

double area() {

switch (shape) {

case RECTANGLE:

return length * width;

case CIRCLE:

return Math.PI * (radius * radius);

default:

throw new AssertionError();

}

}

}

/*

* Refined with Hierarchies

*/

/**

* Class hierarchy replacement for a tagged class

* @author Kaibo

*/

abstract class Figure {

abstract double area();

}

public class Rectangle extends Figure {

// specific fields

final double length;

final double width;

Rectangle(double length, double width) {

this.length = length;

this.width = width;

}

/*

* Common methods

* @see com.effectivejava.classinterface.Figure#area()

*/

@Override

double area() {

return length * width;

}

}

public class Circle extends Figure {

/**

* specific fields.

*/

final double radius;

Circle(double radius) {

this.radius = radius;

}

/*

* common method

* @see com.effectivejava.classinterface.Figure#area()

*/

@Override

double area() {

return Math.PI * (radius * radius);

}

}

Summary

If you're tempted to write a class with an explicit tag field, think about whether the tag could be eliminated and the class replaced by a hierarchy. When you encounter an existing class with a tag field, consider refactoring it into a hierarchy.