Передавая "это" в Java-конструкторе - PullRequest
15 голосов
/ 10 марта 2010

Посмотрите на следующий код:

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

Мне нужен доступ к ClassAattr в некоторых ClassAHandler методах, среди других атрибутов. Есть ли способ сделать это, не передавая класс origin в конструкторе обработчика. Мне не очень нравится, как это решение "выглядит".

Ответы [ 10 ]

11 голосов
/ 10 марта 2010

Передача this другому методу / объекту из конструктора может быть довольно опасной. Многие гарантии, которые обычно выполняются объектами, не всегда верны, если смотреть на них из конструктора.

Например, если в вашем классе есть поле final (не * static), то обычно вы можете зависеть от того, установлено ли оно в значение и никогда не меняется.

Когда объект, на который вы смотрите, в данный момент выполняет свой конструктор, эта гарантия больше не выполняется.

В качестве альтернативы вы можете отложить создание объекта ClassAHandler до тех пор, пока он не понадобится впервые (например, выполнить ленивую инициализацию в получателе этого свойства).

3 голосов
/ 10 марта 2010

На этой странице есть очень хорошее объяснение того, почему отказ от ссылки "this" является плохой идеей:

http://www.ibm.com/developerworks/java/library/j-jtp0618.html#2

Отметьте раздел «Не публиковать ссылку« это »во время строительства»

3 голосов
/ 10 марта 2010

Вы можете использовать внутренние классы, тогда между этими двумя экземплярами существуют неявные родительско-дочерние отношения. (Но я не знаю, действительно ли это лучше).

public class ClassA {
    private boolean ClassAattr = false;

    public class ClassAHandler extends GeneralHandler {

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

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

Если вы передадите this, подклассу потребуется получить доступ к родительскому значению с помощью parent.classAattr. Мы можем задаться вопросом, правильно ли это в соответствии с законом Деметры .

В таком случае ClassA передает всю информацию, которую ClassAHandler требует в конструкторе. Если обработчику требуется значение ClassAttr, передайте его в конструкторе.

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

Но параметр передается по значению, поэтому я не знаю, работает ли он для вас.

Третий вариант - немного изменить дизайн и включить в обработчик boolean. Затем ClassA получает доступ к значению ребенка с помощью handler.handlerAttr. Ребенок ничего не знает о родителе, но родитель может получить столько информации о ребенке, сколько ему нужно. Это лучше в отношении закона Деметры .

public class ClassAHandler extends GeneralHandler {     
   boolean handlerAttr;

   public ClassAHandler() {       
   }
}
3 голосов
/ 10 марта 2010

Создание метода registerHandler (обработчик ClassA).

Нет способа создать обработчик для чего-то, о чем не знает обработчик.

1 голос
/ 28 сентября 2012
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);
    }
}

Итак, я добавил утверждение classAttr = true;

Оператор System.out.println выведет false . Это потому, что построение ClassA не было завершено в тот момент.

Поэтому я предлагаю добавить еще один метод в classA, который создаст ClassAHandler, и тогда classAHandler получит полностью построенный ClassA объект

Чтобы код выглядел следующим образом.

public class ClassA {
    private boolean ClassAattr = false;

    public ClassA() {    

        classAttr = true;
    }

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

Так что кодовая последовательность будет new ClassA().init() и будет отлично работать

1 голос
/ 10 марта 2010

Если я правильно понимаю, вам нужен обработчик для ссылки на ClassA, но вы не хотите устанавливать его из конструктора ClassA? Если это так, то вы можете отделить конструкцию от «подключения», используя фабричный шаблон, который не позволит вашему ClassA узнать о классе ClassAHandler. Вроде как это:

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

}
0 голосов
/ 17 марта 2013

prevNode.nex=this что это значит?

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

    Node(Object element, Node prevNode) { 
      this.element = element; 
      prevNode.next = this; 
    }
}
0 голосов
/ 10 марта 2010

В коде, который вы вставили, нет ничего плохого, однако вы можете использовать нестатический внутренний класс, чтобы сделать вещи (возможно) чище:

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
    }
}
0 голосов
/ 10 марта 2010

Вы можете сделать ClassAHandler внутренним классом ClassA. Это будет иметь доступ к членам ClassA.

0 голосов
/ 10 марта 2010

Напишите метод получения для ClassAattr, как

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

Чтобы вы могли получить к нему доступ как ca.isClassAattr ();

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...