2010-03-10 15 views
16

Mira en el siguiente código:"este" en el constructor java

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

necesito para acceder a ClassAattr en algunos ClassAHandler métodos, entre otros atributos. ¿Hay alguna manera de hacerlo sin pasar la clase de origen en el constructor del controlador? Realmente no me gusta cómo se ve esta solución.

Respuesta

11

Pasar this a otro método/objeto desde el interior del constructor puede ser bastante peligroso. Muchas garantías que los objetos suelen cumplir no son necesariamente ciertas, cuando se las mira desde dentro del constructor.

Por ejemplo, si su clase tiene un campo final (no static), entonces normalmente puede depender de que se establezca en un valor y nunca cambie.

Cuando el objeto que mira está ejecutando actualmente su constructor, esa garantía ya no es verdadera.

Como alternativa, podría retrasar la construcción del objeto ClassAHandler hasta que se necesite por primera vez (por ejemplo, haciendo una inicialización diferida en el captador de esa propiedad).

3

Cree un método registerHandler (ClassA handler).

No hay forma de crear un controlador para algo que el manejador no conoce.

0

escribir un método getter para ClassAattr, como

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

Así que se puede obtener acceso a ella como ca.isClassAattr();

0

Puede hacer que ClassAHandler sea una clase interna de ClassA. Tendría acceso a los miembros de ClassA.

3

Puede usar clases internas, hay una relación padre-hijo implícita entre las dos instancias. (Pero no sé si realmente es mejor).

public class ClassA { 
    private boolean ClassAattr = false; 

    public class ClassAHandler extends GeneralHandler { 

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

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

Si pasa this, la subclase tendrán que acceder al valor padre con parent.classAattr. Podemos preguntarnos si es correcto según el law of demeter.

Otra opción sería que ClassA pase toda la información que ClassAHandler requiere en el constructor. Si el controlador requiere el valor de ClassAttr, páselo en el constructor.

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

Pero el parámetro se pasa por valor, así que no sé si funciona para usted.

Una tercera opción sería cambiar un poco el diseño y tener el boolean en el controlador. Luego ClassA accede al valor del niño con handler.handlerAttr. El niño no sabe nada sobre el padre, pero el padre puede acceder a la mayor cantidad de información que desee del niño. Esto es mejor con respecto al law of demeter.

public class ClassAHandler extends GeneralHandler {  
    boolean handlerAttr; 

    public ClassAHandler() {  
    } 
} 
0

no hay nada malo con el código que ha pegado, sin embargo se puede utilizar una clase interna no estática para hacer las cosas (posiblemente) más limpio:

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

Si entiendo correctamente, necesita que el controlador tenga una referencia a ClassA, pero no desea configurar esto desde el constructor de ClassA? Si ese es el caso, entonces podría separar la construcción de "cablear hacia arriba" usando un patrón de fábrica, lo que evitará que su ClassA tenga que saber sobre la clase ClassAHandler. Algo así como esto:

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

así que he añadido la declaración classAttr = true;

La declaración System.out.println imprimirá falsa. Esto se debe a que la construcción de ClassA no se completó en ese momento.

Así que mi sugerencia es añadir otro método en el classA que creará el ClassAHandler y luego el classAHandler recibirá construida totalmente ClassA objeto

para que el código se verá así.

public class ClassA { 
    private boolean ClassAattr = false; 

    public ClassA() {  

     classAttr = true; 
    } 

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

Para que la secuencia de código será new ClassA().init() y funcionará perfectamente

0

prevNode.nex=this ¿qué significa?

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

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