2016-07-29 14 views
4

ich den folgenden Code habe:Ist es in Ordnung und sicher mit Verweisen auf Konstruktor übergeben zu arbeiten - Java

public class Triangle { 

    private Point left; 
    private Point right; 
    private Point top; 

    public Triangle(Point left, Point right, Point top) { 
     this.left = left; 
     this.right = right; 
     this.top = top; 
    } 

    // more program logic... 
} 

ich mich gefragt, ob es in Ordnung, und sicher ist, ein Objekt so zu konstruieren, weil ich fürchte, dass einige der drei Variablen vom Typ Point von außen modifiziert werden können (Break Encapsulation). Zum Beispiel:

public static void main(String[] args) { 

    Point left = new Point(0.0, 1.0); 
    Point right = new Point(2.4, 3.2); 
    Point top = new Point(5.8, 2.0); 

    Triangle t = new Triangle(left, right, top); 

    top.setX(10.2); 
    top.setY(23.4); 
} 

Dies wird zweifellos das gleiche „top“ Objekt bearbeitet, die im Dreieck Variable referenziert ist wird. So ist das Update die folgenden innerhalb des Dreiecks-Konstruktor tun:

public Triangle(Point left, Point right, Point top) { 
    this.left = new Point(left); 
    this.right = new Point(right); 
    this.top = new Point(top); 
} 

(bedenken Sie, dass ich eine Kopie Konstruktor in der Klasse Point haben, so dass die drei Aussagen über gültig sind)

Antwort

4

Sie könnten klonen die ursprünglichen Punkte im Konstruktor und halten die Klone vor der Außenwelt verborgen. Wenn Point bereits implementiert Cloneable oder wenn Sie es selbst implementieren können, verwenden Sie es so:

public Triangle(Point left, Point right, Point top) { 
    this.left = left.clone(); 
    this.right = right.clone(); 
    this.top = top.clone(); 
} 

Wenn Point nicht Cloneable nicht implementiert, und Sie haben keinen Zugriff auf den Quellcode, nur Klon Punkte manuell:

public Triangle(Point left, Point right, Point top) { 
    this.left = new Point(left.getX(), left.getY()); 
    this.right = new Point(right.getX(), right.getY()); 
    this.top = new Point(top.getX(), top.getY()); 
} 
+0

Point implementiert nicht Cloneable, aber ich habe einen Kopierkonstruktor erstellt, der einen Point akzeptiert und im Grunde einen Point basierend auf dem anderen Konstrukt erstellt, ähnlich wie Ihre zweiten Vorschläge. –

3

Es ist eine sehr gute Frage zu stellen.

Es ist nicht immer eine schlechte Sache haben veränderlichen Zustand. Sie könnten diese Dreieck-Objektinstanz beispielsweise an ein Anzeigeprogramm senden. Wenn Sie die Punktkoordinaten ändern, kann das Dreieck auf dem Bildschirm animiert werden.

Es ist der Anwendungsfall und das Problem, das es lösen soll.

Wenn Sie sich entschieden haben, dass für Ihren Anwendungsfall das gesamte Objektdiagramm (dieses Objekt, meine Kinder und Kinder usw.) nach der Erstellung unveränderlich sein sollte, gibt es Möglichkeiten, dies sicherzustellen.

Für ein unveränderliches Objekt wirklich unveränderlich zu machen, gibt es einige gute Führung hier: http://www.javapractices.com/topic/TopicAction.do?Id=29

Wenn die Objektsammlungen als Eigenschaften haben, könnten Sie Immutable oder Unmodifiable Sammlungen verwenden je nach Bedarf: Java Immutable Collections

Schließlich Wenn Sie den veränderbaren Status zulassen und den Überblick behalten möchten, können Sie sich mit dem untergeordneten Objekt als Beobachter registrieren. When should we use Observer and Observable

Wiederum ist das Prinzip, so wenig wie möglich von veränderlichem Zustand zu halten. Mit anderen Worten, bewahren Sie Objekte so oft wie möglich unveränderbar auf. Unveränderbare Sammlungen sind leicht zu finden und einfach zu benutzen. Das Problem liegt in unseren benutzerdefinierten Klassen.

Wenn Sie Ihr benutzerdefiniertes Objekt/Modellobjekt vollständig unveränderbar gemacht haben, haben Sie möglicherweise Situationen, in denen Sie ganze Objektgraphen kopieren würden, um eine einzelne Eigenschaft zu ändern.

Also, sei vorsichtig. Besonders bei Sammlungen ist es einfach zu machen.

Mit dem objektorientierten Programmierparadigma ist es schwierig, die Veränderlichkeit zu vermeiden. Funktionale Programmierung soll viel mehr mit Unveränderlichkeit ausgerichtet sein. Vielleicht möchten Sie Haskell oder Scala besuchen, nur um einen Eindruck zu bekommen.

https://softwareengineering.stackexchange.com/questions/232711/complete-immutability-and-object-oriented-programming

+0

Ja, Sie haben definitiv Recht, das hängt davon ab, wie Ihre Anwendung funktionieren soll. Danke für die gründliche Antwort! –

1

Wenn Sie eine Kopie Konstruktor haben, dann sind Sie sicher mit, dass die Verwendung. Andernfalls können Sie clone verwenden, wenn Punkt implementiert cloneable.