Effective Java Third edition--23. Use class hierarchy instead of label class first

Source: Internet
Author: User

Tips
"Effective Java, third Edition" an English version has been published, the second edition of this book presumably many people have read, known as one of the four major Java books, but the second edition of 2009 published, to now nearly 8 years, but with Java 6, 7, 8, and even 9 of the release, the Java language has undergone profound changes.
In the first time here translated into Chinese version. For everyone to learn to share.

23. Use class hierarchies rather than label classes as a priority

Sometimes you may encounter a class whose instance has two or more styles, and contains a label attribute (tag field) that represents the style of the instance. For example, consider this class, which can represent a circle or a rectangle:

 //Tagged class-vastly inferior to a class Hierarchy!class figure {enum Shape {RECTANGLE, CIRCLE};    Tag field-the shape of this figure final shape shape;    These fields was used only if shape is RECTANGLE double length;    Double width;    This field was used only if the 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 (shape); }    }}

Such a label class has many drawbacks. Their cluttered boilerplate code, including enumeration declarations, tag properties, and switch statements. is less readable because multiple implementations are mixed together in a class. Memory usage increases because the instance burden belongs to areas that are unrelated to other styles. The property cannot be final unless the constructor initializes an unrelated property, resulting in more boilerplate code. Construction method with the help of the compiler, you must set the label properties and initialize the correct data properties: If you initialize the wrong property, the program will fail at run time. You cannot add it to a tagged class unless you can modify its source file. If you add a style, you must remember to add a case to each switch statement, or the class will fail at run time. Finally, the data type of an instance does not provide any clues about the style. In short, label classes are lengthy, error-prone, and inefficient.

Fortunately, an object-oriented language like Java provides a better choice for defining a single data type that can represent multiple styles of objects: Subtype (subtyping). The tag class is just a simple imitation of a class hierarchy.

To convert a label class to a class hierarchy, first define an abstract class that contains an abstract method, and the behavior of the label class depends on the tag value. In Figure a class, there is only one such method, which is the area method. This abstract class is the root of the class hierarchy. If there are any methods whose behavior does not depend on the value of the labels, place them in this class. Similarly, if you have all the methods that use the data attributes, put them in this class. FigureThis type-independent method or property does not exist in the class.

Next, define a specific subclass of the root class for each type of the original label class. In our case, there are two types: round and rectangular. Include data fields that are specific to the type of change in each subclass. In our example, the RADIUS attribute is a circle, and the length and width properties are rectangular. Also include the appropriate implementation of each abstract method in the root class in each subclass. Here is the class hierarchy that corresponds to the figure class:

// Class hierarchy replacement for a tagged classabstract class Figure {    abstract double area();}class Circle extends Figure {    final double radius;    Circle(double radius) { this.radius = radius; }    @Override 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;    }    @Override double area() { return length * width; }}

This class level corrects each of the drawbacks of the previously mentioned label classes. The code is straightforward and does not contain boilerplate files in the original text. Each type of implementation is assigned by its own class, and none of these classes are occupied by irrelevant data attributes. All of the properties are final. The compiler ensures that each class's construction method initializes its data properties, and each class has an implementation for each of the abstract methods declared in the root class. This eliminates the possibility of run-time failures caused by a lack of switch-case statements. Multiple programmers can inherit class hierarchies independently and interoperate with each other without having to access the source code of the root class. Each type has a separate data type associated with it, allowing the programmer to indicate the type of the variable and restrict the variable and input parameters to a specific type.

Another advantage of class hierarchies is that they can reflect a natural hierarchical relationship between types, which increases flexibility and improves the efficiency of compile-time type checking. It is assumed that the label class in the original example also allows the use of squares. The class hierarchy can be used to reflect that a square is a special rectangle (assuming that they are immutable):

lass Square extends Rectangle {    Square(double side) {        super(side, side);    }}

Note that the properties in the above layers are directly accessible, not access methods. For the sake of brevity, if the class hierarchy is public (entry 16), it will be a bad design.

In short, there are few cases where a label class is applicable. If you want to write a class with an explicit tag attribute, consider whether the label property can be deleted, and whether the class is replaced by the class hierarchy. When you encounter an existing class with a tag attribute, consider refactoring it into a class hierarchy.

Effective Java Third edition--23. Use class hierarchy instead of label class first

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.