#java
#java
Вопрос:
Я работаю над небольшим университетским заданием. Устав от написания трех строк кода для добавления кнопок, я написал небольшую служебную функцию:
private JButton addButton(Container container, String text) {
JButton button = new JButton(text);
button.addActionListener(this);
container.add(button);
return button;
}
Затем, конечно, появился служебный метод для добавления текстовых полей:
private JTextField addInput(Container container, int width) {
JTextField input = new JTextField(width);
input.addActionListener(this);
container.add(input);
return input;
}
Как вы можете видеть, они почти идентичны. Итак, я попытался уменьшить количество строк, используя всемогущий метод, который добавлял бы что угодно к любой другой вещи.
private Component addComponent(Container container, Component component) {
component.addActionListener(this);
container.add(component);
return component;
}
Теперь я должен признать, что начинаю думать, что, возможно, эти сверхмалые служебные функции немного абсурдны.
Однако, несмотря на это, мой всемогущий addComponent
метод не сработал. Вместо этого жаловаться, что у Component
них нет ActionListeners
.
Единственный способ, которым я могу обойти это, — это иметь MyJButton
и MyJTextField
оба из которых наследуются от MyComponent
того addActionListener
, у которого есть метод. Первоначальная цель упрощения и устранения повторений была выброшена из окна?
Как это можно / должно быть сделано? Я новичок в Java и строго типизированных материалах!
Ответ №1:
Я бы сказал, что ваш текущий подход (куча похожих вспомогательных методов) настолько хорош, насколько вы сможете.
Некоторые вещи неэлегантны, и вы мало что можете с этим поделать.
Риск попытки объединить методы (в соответствии с ответом @leonbloy) заключается в том, что вы заменяете безопасность статического типа безопасностью типа во время выполнения; т. е. ClassCastExceptions
при сбое приведения типов … или хуже.
С лингвистической точки зрения, что необходимо, так это способ для приложения «украсить» существующую иерархию классов дополнительным методом (или методами) и иметь методы, вызываемые полиморфной диспетчеризацией, так же, как вы делаете с обычными методами экземпляра.
Это можно смоделировать с использованием шаблона декоратора, но для этого требуется некоторая довольно тяжеловесная инфраструктура … если в иерархии классов нет перехватов для поддержки встроенного шаблона.
Ответ №2:
Проблема в том, что нет интерфейса, который предоставляет
addActionListener(ActionListener l)
если бы это было так, вы могли бы сделать
public <T extends Component amp; ActionListenable> Component addComponent(Container container, T component) {
component.addActionListener(this);
container.add(component);
return component;
}
Предполагая, что поддельный ActionListenable является вышеупомянутым интерфейсом.
Ответ №3:
Существует несколько подходов. Если вы точно знаете, что ваш метод addComponent
будет действовать только с параметрами JTextField
и JButton
, вы можете выполнять явные приведения
if (component instanceof JButton){
((JButton)component).addActionListener(this);
}
else if (component instanceof JTextField){
((JTextField)component).addActionListener(this);
}
Не очень элегантно, не очень хорошая практика, но этого может быть достаточно в вашем сценарии.
Если вы хотите вызвать, addActionListener
если у Component
есть этот метод, вы можете использовать отражение — но я подозреваю, что это было бы излишним для вашей цели.
PS: В случае, если вам это более понятно, это было бы эквивалентно второй строке:
JButton button = (JButton)component; // explicit cast -we know for sure that this is a JButton
button.addActionListener(this);
Комментарии:
1. Это было бы неподходящим местом для использования отражения. Вы бы просто делали то же самое (вероятно) менее эффективным и (определенно) более хрупким способом.