[JAVA] Punkt 23: Bevorzugen Sie Klassenhierarchien gegenüber markierten Klassen

23. Wählen Sie eine Klassenhierarchie aus markierten Klassen aus

Tagged Klasse

Eine Klasse, die zwei oder mehr Arten von Merkmalen anzeigt und zwischen ihnen mit Tags wechselt, die diese Merkmale im Feld aufweisen, wird als markierte Klasse bezeichnet. Die folgende Klasse ist ein Beispiel und es ist möglich, Kreise und Rechtecke darzustellen.

package tryAny.effectiveJava;

class Figure {
    enum Shape {
        RECTANGLE, CIRCLE
    }

    //Formtyp halten
    final Shape shape;

    //Nur verwenden, wenn die Form RECHTECKIG ist
    double length;
    double width;

    //Nur verwenden, wenn die Form KREIS ist
    double radius;

    //Konstruktor für Kreis
    Figure(double radius) {
        shape = Shape.CIRCLE;
        this.radius = radius;
    }

    //Konstruktor für Rechteck
    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();
        }
    }
}

Solche markierten Klassen haben viele Nachteile. Unten finden Sie eine Liste der Nachteile.

Tagged Klassenalternative: Klassenhierarchie

Wenn es sich um eine objektorientierte Sprache handelt, kann sie mithilfe einer Klassenhierarchie verbessert werden.

Das Verfahren zum Ändern von einer markierten Klasse zu einer Klassenhierarchie lautet

  1. Erstellen Sie eine abstrakte Klasse und definieren Sie die Methode (Bereichsmethode im obigen Beispiel), deren Operation durch den Tag-Wert als abstrakte Methode umgeschaltet wird.
  2. Fügen Sie tagwertunabhängige Methoden und Feldwerte in die abstrakte Klasse ein (im obigen Beispiel gibt es so etwas nicht).
  3. Erstellen Sie eine Unterklasse für das Teil, das den Merkmalen der markierten Klasse entspricht. (Kreis, Rechteck im obigen Beispiel)
  4. Fügen Sie in jede Unterklasse ein charakteristisches Feld ein. (Radius für Kreis, Länge, Breite für Rechteck)

Das obige Korrekturergebnis ist wie folgt.

package tryAny.effectiveJava;

abstract 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;
    }
}

Auf diese Weise werden die Nachteile der oben erwähnten markierten Klasse beseitigt.

Andere gute Punkte der Klassenhierarchie

Die Klassenhierarchie kann die tatsächlichen hierarchischen Beziehungen zwischen Typen widerspiegeln, wodurch die Flexibilität (?) Und die Fehlerprüfung zur Kompilierungszeit verbessert werden können.

Wenn im obigen Beispiel ein Quadrat hinzugefügt wird, kann dies anhand der Merkmale der Klassenhierarchie wie folgt beschrieben werden.

class Square extends Rectangle {

    Square(double side) {
        super(side, side);
    }
}

Recommended Posts

Punkt 23: Bevorzugen Sie Klassenhierarchien gegenüber markierten Klassen
Punkt 42: Bevorzugen Sie Lambdas gegenüber anonymen Klassen
Punkt 28: Listen Arrays vorziehen
Punkt 65: Schnittstellen der Reflexion vorziehen
Punkt 43: Bevorzugen Sie Methodenverweise auf Lambdas
Punkt 39: Bevorzugen Sie Anmerkungen gegenüber Namensmustern
Punkt 85: Bevorzugen Sie Alternativen zur Java-Serialisierung
Punkt 58: Bevorzugen Sie für jede Schleife herkömmliche Schleifen
Punkt 61: Bevorzugen Sie primitive Typen gegenüber primitiven Boxen
Wählen Sie eine Klassenhierarchie aus markierten Klassen
Punkt 81: Bevorzugen Sie Parallelitätsdienstprogramme, um zu warten und zu benachrichtigen
Punkt 80: Ziehen Sie Executoren, Aufgaben und Streams Threads vor
Punkt 89: Für die Steuerung bevorzugen Sie Aufzählungstypen gegenüber readResolve
Punkt 47: Sammlung als Rückgabetyp dem Stream vorziehen
Punkt 25: Beschränken Sie Quelldateien auf eine einzelne Klasse der obersten Ebene
Klasse zu zählen