Удаление анонимного слушателя

При попытке применить стиль реализации прослушивателя с использованием анонимного или вложенного класса, чтобы скрыть методы уведомления для других целей, кроме прослушивания (т.е. я не хочу, чтобы кто-либо мог вызывать actionPerformed). Например, из прослушиватель действий Java: реализует против анонимного класса:

public MyClass() {
    myButton.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e) {
            //doSomething
        }
    });
}

Вопрос в том, есть ли элегантный способ снова удалить слушателя, используя эту идиому? Я понял, что создание экземпляра ActionListener не создает каждый раз одинаковые объекты, поэтому Collection.remove() не удалит первоначально добавленный объект.

Чтобы считаться равными, слушатели должны иметь одинаковое внешнее это. Чтобы реализовать equals, мне нужно было бы получить внешнее this для другого объекта. Так что это будет примерно так (что я нахожу немного неуклюжим):

interface MyListener {
    Object getOuter();
}

abstract class MyActionListener extends ActionListener
    implement MyListener {
}

public MyClass() {
    myButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            // doSomething on MyClass.this
        }
        public Object getOuter() {
           return MyClass.this;
        }
        public boolean equals(Object other)
        {
           if( other instanceof MyListener )
           {
              return getOuter() == other.getOuter();
           }
           return super.equals(other);
        });
    }
 }

Или мне придется оставить объект ActionListener в качестве (закрытого) члена внешнего класса?


person skyking    schedule 29.04.2015    source источник
comment
Вы можете сделать эти объекты равными, переопределив equals() в анонимном классе, не так ли?   -  person Alex Salauyou    schedule 29.04.2015
comment
Почему вы не можете использовать removeActionListener?   -  person CKing    schedule 29.04.2015
comment
removeActionListener зависит от удаляемого объекта и сравнивается с объектом, переданным в removeActionListener. Я отредактировал вопрос с объяснением, почему я думаю, что реализация equals() повлечет за собой некоторые накладные расходы.   -  person skyking    schedule 04.05.2015


Ответы (2)


Назначьте анонимного слушателя частной локальной переменной, например.

public MyClass() {
    private Button myButton = new Button();
    private ActionListener actionListener = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            //doSomething
        }
    };
    private initialize() {
        myButton.addActionListener(actionListener);
    }
}

Позже вы можете использовать закрытую переменную actionListener, чтобы снова удалить его.

person Uwe Plonus    schedule 29.04.2015
comment
Хотя это не тот ответ, который я хотел, но похоже, что нужно прибегнуть к назначению слушателя локальной переменной. - person skyking; 22.05.2015

В этом и прелесть анонимных классов — они анонимны :-)

Нет, нет такой же элегантной идиомы, чтобы снова удалить слушателя. Единственный способ - перебрать getActionListeners() и удалить тот, который вы хотите. Конечно, если есть только один, это так же просто, как:

myButton.removeActionListener( myButton.getActionListeners()[ 0 ] );

что не так уж и некрасиво.

person Anders R. Bystrup    schedule 29.04.2015