Не сильно ошибусь, если предположу, что мало кто активно использует эту возможность языка. Для тех кто не помнит, что это такое можно почитать здесь. Я же переду к практике.
Наткнулся на проблему: надо послать уже существующее событие (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) { if (event instanceof ICommandEvent) { ((ICommandEvent) event).setCommand(command); } else { throw new IllegalStateException("Only ICommandEvent allowed"); } bus.fire(event); } }); return new WidgetComponent(button); }
Ну некрасиво! К тому же в него можно передать любое событие, а обнаружится это только при запуске, что нехорошо.
И тут пора вспомнить о теме этой заметки — multiple bounds 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); }
Ровно то, что и требовалось.