标签类值带有两种甚至多种风格的实例的类,如一个表示圆或者矩形的类:
class Figure { enum Shape { RECTANGLE, CIRCLE }; final Shape shape; double length; double width; double radius; Figure(double radius) { shape = Shape.CIRCLE; this.radius = radius; } 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(); } }}
这种标签类过于冗长,容易出错,并且效率低下。
在Figure类中,只有area方法是矩形或者圆都有的,将它放在类层次的根。
abstract class Figure { abstract double area();}class Circle extends Figure { final double radius; Circle(double radius) { this.radius = radius; } double area() { return Math.PI * radius * radius; }}class Rectangle extends Figure { final double length; final double width; Rectangle(double length, double width) { this.length = length; this.width = width; } double area() { return length * width; }}
类层次可以反映正方形是一种特殊的矩形:
class Square extends Rectangle { square(double side) { super(side, side); }}
上述的域是被直接访问的,而不是通过访问方法,应该使用访问方法。
标签类很少适用的时候,当想要编写一个包含显式标签域的类时,考虑能否用类层次代替,当遇到一个包含标签域的现有类时,考虑将它重构到一个层次结构中。