Pull to refresh

Eщё раз о шаблонах (generic) в Java

На днях наткнулся на проблему: надо послать событие в GWT по кнопке, но перед посылкой поставить атрибут (Command). Казалась бы, при чём здесь шаблоны…

А вот при чём:

Сам метод для создания кнопки тривиален (command – поле класса):

Component createEventLink(String link, final Event<?> event) {
	TextButton button = new TextButton(link, new SelectHandler() {
		@Override
		public void onSelect(SelectEvent e) {
			//event.setCommand(command);
			bus.fire(event);
		}
	});
	return new WidgetComponent(button);
}

Проблема в строчке:

//event.setCommand(command);

Такого метода у объекта Event нет. Решение, вроде, очевидное: унаследовать наше события от промежуточного класса CommandEvent, у которого будет этот метод и который унаследован от Event. Наш метод выглядит теперь так:

Component createEventLink(String link, final CommandEvent<?> event) {
	TextButton button = new TextButton(link, new SelectHandler() {
		@Override
		public void onSelect(SelectEvent e) {
			event.setCommand(command);
			bus.fire(event);
		}
	});
	return new WidgetComponent(button);
} 

Эврика? Ха! Тут мы обнаруживаем, что одно из наших событий уже унаследовано от другого дочернего класса (e.g. GwtEvent) и никак не может наследовать наш класс CommandEvent.

Следующий шаг — создаём интерфейс ICommandEvent c методом setCommand() и каждое наше событие реализует его. Наш метод выглядит теперь так:

Component createEventLink(String link, final Event event) {
	TextButton button = new TextButton(link, new SelectHandler() {
		@Override
		public void onSelect(SelectEvent e) {
			try {
				((ICommandEvent) event).setCommand(command);
			} catch (ClassCastException ex) {
				throw new IllegalStateException("Only ICommandEvent allowed");
			}
			bus.fire(event);
		}
	});
	return new WidgetComponent(button);
}

Ну некрасиво! К тому же в него можно передать любое событие, а обнаружится это только при запуске, что нехорошо.

И тут пора вспоменить о теме нашей статьи (поста?) — шаблоны (generic) в Java. С ними наш метод выглядит так:

<E extends Event<?> & ICommandEvent> Component createEventLink(String link, final E event) {
	TextButton button = new TextButton(link, new SelectHandler() {
		@Override
		public void onSelect(SelectEvent e) {
			event.setCommand(command);
			bus.fire(event);
		}
	});
	return new WidgetComponent(button);
}

Ровно то, что и и требовалось.

P.S.: Если вы нашли этот пост полезеным, то в ваших силах сделать так, чтобы он не исчез через 14 деней.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.