Можете ли вы привести объект к объекту, который реализует интерфейс? (ДЖАВА) - PullRequest
0 голосов
/ 07 июня 2010

Можете ли вы привести объект к объекту, который реализует интерфейс? Сейчас я создаю графический интерфейс и не хочу переписывать код подтверждения / отмены (всплывающее окно подтверждения) снова и снова.

Итак, я пытаюсь написать класс, который будет передан класс , в котором он используется, и сообщает класс , нажал ли пользователь «Подтвердить» или «Отмена». Класс всегда реализует определенный интерфейс.

Код:

class ConfirmFrame extends JFrame implements ActionListener
{
    JButton confirm = new JButton("Confirm");
    JButton cancel = new JButton("Cancel");
    Object o;

    public ConfirmFrame(Object o)
    {
        // Irrelevant code here
        add(confirm);
        add(cancel);
        this.o = (/*What goes here?*/)o;
    }

    public void actionPerformed( ActionEvent evt)
    {
        o.actionPerformed(evt);
    }
}

Я понимаю, что я, вероятно, слишком усложняю вещи, но теперь, когда я столкнулся с этим, я действительно хочу знать, можете ли вы привести объект к другому объекту, который реализует определенный интерфейс.

Ответы [ 3 ]

3 голосов
/ 07 июня 2010

Вы можете приводить объекты вверх или вниз по иерархии типов; иногда это безопасно, а иногда нет. Если вы попытаетесь привести переменную к несовместимому типу (то есть попытаться убедить компилятор в том, что это не так), вы получите исключение во время выполнения (т.е. ошибка). Переход к более общему типу (например, замена ActionListener на Object) называется апкастингом и всегда безопасен, если предположить, что класс, к которому вы приводите, является одним из предков вашего текущего класса (и Object является предком всего в Java). Переход к более конкретному типу (например, приведение от ActionListener к MySpecialActionListener) работает только в том случае, если ваш объект является экземпляром более конкретного типа.

Итак, в вашем случае звучит так, будто вы пытаетесь сказать, что ConfirmFrame реализует интерфейс ActionListener. Я предполагаю, что этот интерфейс включает в себя:

public void actionPerformed( ActionEvent evt);

И здесь, в вашей реализации этого виртуального метода, вы хотите делегировать evt тому объекту, который o был передан в конструктор. Проблема в том, что Object не имеет метода с именем actionPerformed; только более специализированный класс (в данном случае, реализация ActionListener, подобная вашему ConfirmFrame классу) будет иметь его. Так что вы, вероятно, хотите, чтобы этот конструктор взял ActionListener вместо Object.

class ConfirmFrame extends JFrame implements ActionListener
{
    JButton confirm = new JButton("Confirm");
    JButton cancel = new JButton("Cancel");
    ActionListener a;

    public ConfirmFrame(ActionListener a)
    {
        // Irrelevant code here
        add(confirm);
        add(cancel);
        this.a = a;
    }

    public void actionPerformed( ActionEvent evt)
    {
        a.actionPerformed(evt);
    }
}

Конечно, более понятные имена переменных, чем "o" или "a", вероятно, помогут вам (и всем, кто читает это) понять, почему вы передаете ActionListener в другой ActionListener.

0 голосов
/ 07 июня 2010

Пример использования вышеприведенного ответа::)

class MyFrame extends Frame{ 



         ActionListener confirmListener = new ActionListener (){

                //implementation of the ActionListener I
                   public void actionPerformed(ActionEvent e){

                          if ( e.getActionCommand().equals("Cancel")){
                              // do Something
                          }
                          else if(e.getActionCommand().equals("Confirm")){
                             // do Something
                         }
                   } 
         };

         ConfirmFrame confirmDialog = new ConfirmDialog(confirmListener);

         //code that uses the ConfirmFrame  goes here....

}
0 голосов
/ 07 июня 2010

Конечно, вы можете - применяется обычный синтаксис для приведения. Вы даже можете объявить тип параметра как интерфейс, а не Object.

Редактировать: Конечно, тип переменной также должен быть интерфейсом или, в качестве альтернативы, вы можете привести его при вызове метода, т. Е.

ActionPerformer o;
...
this.o = (ActionPerformer)o;

или

((ActionPerformer)this.o).actionPerformed(evt);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...