2010-05-06 3 views
4

У меня есть этот простой интерфейс/класс:Отражение: брось объект подкласса без использования InstanceOf

public abstract class Message {} 

public class Message1 extends Message {} 

public class Message2 extends Message {} 

И утилита класс:

public class Utility { 
    public void handler(Message m) { 
     System.out.println("Interface: Message"); 
    } 

    public void handler(Message1 m) { 
     System.out.println("Class: Message1"); 
    } 

    public void handler(Message2 m) { 
     System.out.println("Class: Message2"); 
    } 
} 

Теперь главный класс:

public static void main(String[] args) { 

    Utility p = new Utility(); 

    Message1 m1 = new Message1(); 
    p.handler(m1); 

    Message m = (Message) m1; 
    p.handler(m); 

} 

Выходной сигнал

> Class: Message1 
> Interface: Message 

Я хотел бы, чтобы p.handler(m) вызов метода p.handler(m:Message1)

Я не хочу использовать команду instanceof «ручной», потому что у меня много дел:

if(m instance of Message1) 
p.handler((Message1)m) 
else if (m instanceof Message2) 
p.handler((Message2)m) 
... 

Если я называю m.getClass() я получаю «mypackage.Message1», поэтому подкласс, а не суперкласс.

Стараюсь с этим кодом (использование отражения):

p.handler(m.getClass().cast(m)); 

Но выход

> Interface: Message 

Итак, это моя проблема. Я бы выполнил запуск суперкласса объекта subclassobject без использования команды «code command» istanceof.

Я бы право команды, как это:

p.handler((m.getclass)m); 

Как я могу получить? Возможно?

+0

Пожалуйста, очистите форматирование! У вас есть код, отформатированный как код, блок-кавычки и текстовый текст. –

+0

Я отформатировал его! – jfabrizio

+0

«Мне бы хотелось, чтобы p.handler (m) вызывал метод p.handler (m: Message1)» - это не то, как работает Java! Java - одноразовая отправка! – polygenelubricants

ответ

7

Java будет вызывать метод на основе информации, известной во время компиляции. Что вы можете сделать, так это добавить метод к интерфейсу, который вызывает правильный метод обработчика для объекта.

public abstract class Message { 

    public abstract void callHandler(Utility utility); 

} 

public class Message1 extends Message{ 

    public void callHandler(Utility utility) { 
     utility.handler(this); 
    } 
} 

Ваши звонки в обработчике стали:

Message m=(Message) m1; 
m.callHandler(p); 

который теперь называет утилиты :: обработчик (Сообщение1), даже если ссылка в основной имеет тип интерфейса передачи сообщений.

+0

@rsp: добавьте ключевое слово abstract для метода callHandler в Message. –

+0

простой, правый и без отражения! Thank – jfabrizio

+0

+1 «что известно во время компиляции» - это ключ – leonbloy

0

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

Message m = new Message1(); 
m.handle(); 

Этот код возвращает «Класс: Сообщение1», как вам нужно.

Смежные вопросы