Загадка инициализации класса Java - PullRequest
1 голос
/ 11 декабря 2010

Я использую GUI Designer NetBeans для создания некоторых JDialog s, которые я затем подклассирую из своего собственного EditorDialog класса.

Прежде чем идти дальше, рассмотрим этот пример кода:

class MyDialog extends EditorDialog {
    private Color someVariableThatTheGuiNeeds = new Color(0,50,100);

    public MyDialog() {
        super(true);
    }

    //<auto-generated>
    private void initComponents() { //note this is private!
        //...
    }
    //</auto-generated>
}

abstract class EditorDialog extends JDialog {
    public EditorDialog() {
        super(null,true);
    }
    public EditorDialog(boolean stuffNeedsDone) {
        super(null,true);
        //initComponents();
        doStuffAfterGuiInitialized();
    }
}

Проблема в том, что я не могу позвонить initComponents() из моего суперкласса, потому что он закрытый.

Чтобы обойти это, я попытался обойти классы:

//in EditorDialog
public EditorDialog(boolean stuffNeedsDone) {
    super(null,true);
    workaround();
    doStuffAfterGuiInitialized();
}
protected abstract void workaround();

//in MyDialog
@Override
protected void workaround() {
    initComponents();
}

И, конечно, это не работает, потому что someVariableThatTheGuiNeeds не инициализируется при вызове initComponents() из-за способа инициализации:

  • new MyDialog()
    • super(this)
      • EditorDialog(boolean) вызывается
        • super(null,true) вызывается, JDialog делает вещи
        • EditorDialog переменные экземпляраинициализировано
        • workaround()
        • initComponents()
          • doSomethingWith(someVariableThatTheGuiNeeds) -> NullPointerException , поскольку someVariableThatTheGuiNeeds еще не инициализировано
    • СЕЙЧАС someVariableThatTheGuiNeeds инициализировано

Также яне может создать не приватный реферат initComponents() в EditorDialog, потому чтоВидимость при переопределении может стать более общедоступной.

Итак, как мне обойти эту проблему, не делая ее слишком хакерской?

(Если вы не знакомы с NetBeans, я не может редактировать автоматически сгенерированный код, и нет никакой возможности (которую я мог бы найти) изменить модификаторы доступа в методе initComponents().

Ответы [ 2 ]

1 голос
/ 11 декабря 2010

Ваши конструкторы ни в коем случае не должны вызывать не- private методы. Если вам требуется инициализация для ваших диалогов после их создания, вы можете создать метод init(), который должен вызываться после завершения конструктора.

Обратите внимание, имя метода doStuffAfterGuiInitialized() указывает на некоторое недопонимание. Графический интерфейс или даже экземпляр не полностью инициализируется до завершения конструктора.

0 голосов
/ 11 декабря 2010

Это распространенная проблема в Java.Instanciation не является другом подкласса.

Многие используют косвенное решение: вызовите метод init () после полной сборки объекта.

Это часто автоматизируется с помощью фабрики.Все системы инъекций (такие как Spring) делают это регулярно.

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