2010-03-10 11 views
16

Blick in den folgenden Code Passing:"dieser" in Java-Konstruktor

public class ClassA { 
    private boolean ClassAattr = false; 

    public ClassA() {  
     ClassAHandler handler = new ClassAHandler(this); 
    } 
} 

public class ClassAHandler extends GeneralHandler { 
    ClassA ca = null; 

    public ClassAHandler(ClassA classa) { 
     this.ca = classa; 
    } 
} 

brauche ich ClassAattr auf einige ClassAHandler Methoden zuzugreifen, unter anderen Attributen. Gibt es eine Möglichkeit, dies zu tun, ohne die Herkunftsklasse im Handler-Konstruktor zu übergeben. Ich mag es nicht wirklich, wie diese Lösung aussieht.

Antwort

11

Das Übergeben von this an eine andere Methode/Objekt aus dem Konstruktor kann ziemlich gefährlich sein. Viele Garantien, die Objekte normalerweise erfüllen, sind nicht unbedingt wahr, wenn sie aus dem Konstruktor heraus betrachtet werden.

Zum Beispiel, wenn Ihre Klasse ein final (nicht static) Feld hat, dann können Sie normalerweise davon abhängen, dass es auf einen Wert gesetzt ist und sich nie ändert.

Wenn das betrachtete Objekt gerade seinen Konstruktor ausführt, gilt diese Garantie nicht mehr.

Alternativ können Sie die Konstruktion des Objekts ClassAHandler verzögern, bis es zum ersten Mal benötigt wird (z. B. indem Sie im Getter dieser Eigenschaft eine verzögerte Initialisierung durchführen).

3

Erstellen Sie eine registerHandler (ClassA-Handler) -Methode.

Es gibt keine Möglichkeit, einen Handler für etwas zu erstellen, von dem der Handler nichts weiß.

0

eine Getter-Methode für ClassAattr schreiben, wie

  public boolean isClassAattr(){ 
       return this.ClassAattr; 
      } 

Damit Sie Zugriff als ca.isClassAattr() bekommen;

0

Sie können ClassAHandler zu einer inneren Klasse von ClassA machen. Es hätte Zugang zu den Mitgliedern von ClassA.

3

Sie könnten innere Klassen verwenden, dann gibt es eine implizite Eltern-Kind-Beziehung zwischen den beiden Instanzen. (Aber ich weiß nicht, ob es wirklich besser ist).

public class ClassA { 
    private boolean ClassAattr = false; 

    public class ClassAHandler extends GeneralHandler { 

     public ClassAHandler() { 
      // can access ClassAattr 
     } 
    } 

    public ClassA() {  
     ClassAHandler handler = new ClassAHandler(); 
    } 
} 

Wenn Sie this passieren, müssen die Unterklasse mit parent.classAattr den übergeordneten Wert zuzugreifen. Wir können uns fragen, ob es nach der law of demeter korrekt ist.

Eine andere Option wäre dann, dass ClassA alle Informationen übergeben, die ClassAHandler im Konstruktor erfordert. Wenn der Handler den Wert ClassAttr benötigt, übergeben Sie ihn im Konstruktor.

public ClassA() {  
     ClassAHandler handler = new ClassAHandler(classAattr); 
    } 

Aber der Parameter wird nach Wert übergeben, so dass ich nicht weiß, ob es für Sie funktioniert.

Eine dritte Option wäre, das Design ein bisschen zu ändern und die boolean im Handler zu haben. Dann greift ClassA auf den Wert des Kindes mit handler.handlerAttr. Das Kind weiß nichts über den Elternteil, aber der Elternteil kann auf so viele Informationen zugreifen, wie das Kind möchte. Dies ist besser in Bezug auf die law of demeter.

public class ClassAHandler extends GeneralHandler {  
    boolean handlerAttr; 

    public ClassAHandler() {  
    } 
} 
0

es ist nichts falsch mit dem Code ist, dass Sie eingefügt, jedoch können Sie eine nicht statische innere Klasse verwenden, um die Dinge (wohl) Reiniger:

public class ClassA { 
    private boolean ClassAattr = false; 

    public ClassA() {  
     ClassAHandler handler = new ClassAHandler(); 
    } 

    class ClassAHandler extends GeneralHandler { 

     // magically sees the instantiating ClassA members and methods 
    } 
} 
1

Wenn ich richtig verstehe, benötigen Sie den Handler, um einen Verweis auf ClassA zu haben, aber Sie möchten dies nicht innerhalb des Konstruktors von ClassA einrichten? Wenn das der Fall ist, dann könnten Sie Konstruktion trennen von "Verdrahtung" mit einem Fabrikmuster, das Ihre ClassA davon abhält, über die ClassAHandler Klasse zu wissen. Art wie folgt aus:

public class ClassA { 

    private boolean ClassAattr = false; 

    public ClassA() { 
    } 

} 


public class ClassAHandler { 

    private ClassA ca = null; 

    public ClassAHandler(ClassA classa) { 
     this.ca = classa; 
    } 

} 


public HandlerFactory { 

    public ClassAHandler createClassAHandler(ClassA classa) { 
     ClassAHandler handler = new ClassAHandler(classa); 
     return handler; 
    } 

} 
1
public class ClassA { 
    private boolean ClassAattr = false; 
     public ClassA() {  
     ClassAHandler handler = new ClassAHandler(this); 
     classAttr = true; 
    } 
} 

public class ClassAHandler extends GeneralHandler { 
    ClassA ca = null; 

    public ClassAHandler(ClassA classa) { 
     this.ca = classa; 
     System.out.println(ca.classAttr); 
    } 
} 

So habe ich hinzugefügt, um die Aussage classAttr = true;

Die System.out.println Anweisung falsch gedruckt wird. Dies ist, weil die Konstruktion ClassA zu diesem Zeitpunkt nicht abgeschlossen war.

So ist mein Vorschlag, eine andere Methode in classA hinzuzufügen, die die ClassAHandler schaffen und dann die classAHandler voll ClassA Objekt

Damit der Code aussehen wird aufgebaut erhalten.

public class ClassA { 
    private boolean ClassAattr = false; 

    public ClassA() {  

     classAttr = true; 
    } 

    public init() { 
     ClassAHandler handler = new ClassAHandler(this); 
    } 
} 

Damit die Codesequenz new ClassA().init() sein wird und perfekt funktionieren

0

prevNode.nex=this was bedeutet es?

public class DynamicList { 
    private class Node { 
    Object element; 
    Node next; 

    Node(Object element, Node prevNode) { 
     this.element = element; 
     prevNode.next = this; 
    } 
}