Передача “этого” в конструкторе 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;
    }
}

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

15
задан Nissa 9 November 2016 в 20:14
поделиться

8 ответов

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

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

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

4
ответ дан 1 December 2019 в 03:14
поделиться

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

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

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

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

public class ClassAHandler extends GeneralHandler {     
   boolean handlerAttr;

   public ClassAHandler() {       
   }
}
3
ответ дан 1 December 2019 в 03:14
поделиться

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

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

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

0
ответ дан 1 December 2019 в 03:14
поделиться

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

0
ответ дан 1 December 2019 в 03:14
поделиться

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

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
ответ дан 1 December 2019 в 03:14
поделиться

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

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

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

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

11
ответ дан 1 December 2019 в 03:14
поделиться

Создайте метод registerHandler(ClassA handler).

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

3
ответ дан 1 December 2019 в 03:14
поделиться

Если я правильно понимаю, вам нужно, чтобы обработчик имел ссылку на 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;
    }

}
1
ответ дан 1 December 2019 в 03:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: