Как вызвать метод Java на основе типа подкласса? - PullRequest
8 голосов
/ 31 января 2010

Я пытаюсь отправить объекты в отдельный метод в соответствии с их подклассом.

Например, рассмотрим эти 2 объекта

class A extends I {}
class B extends I {}

и метод

void dispatch(I i) {}

в dispatch(), я бы хотел вызвать метод в соответствии с типом i. Следовательно, если i на самом деле имеет тип A, будет вызван метод handlerA(A a). Если это тип B, будет вызываться handlerB(B b) и так далее ... Я пытался с перегрузкой метода, но я думаю, что это не работает

каков наилучший способ достичь этого? Я хотел бы избежать использования оператора if / else ...

Заранее спасибо,

edit: я не могу изменить ни один из этих классов.

Ответы [ 6 ]

4 голосов
/ 31 января 2010

Используйте шаблон Visitor .

Короче говоря, пусть I объявляет метод accept(Visitor<T> ...), а Visitor предоставляет методы onA(A ...), onB(B ...) и т. Д. Ваши реализации интерфейса I будут вызывать соответствующий метод для переданного в Visitor<T>.

Вероятно, не стоит (из-за шаблонного), если у вас есть только 2 конкретных класса, но где-то около 3 или 4 он начинает стоить того - если только избежать дублирующих конструкций if-else.

3 голосов
/ 31 января 2010

Таким образом, в I вы объявляете метод handler() и реализуете его соответствующим образом (т.е. по-разному) в A и B.

Это Полиморфизм:)

1 голос
/ 31 января 2010

После вашего редактирования я предполагаю, что вы не можете редактировать A, B и I; это приводит к плохим новостям:

Вы можете наследовать от A скажем C в этом классе (C), который вы можете назвать super.dispatch(), чтобы вы могли достичь базового класса A.dispatch().

  • Но из-за замысла (нерассмотренного наследования) вы не можете достичь I. Это похоже на вызов super.super, который не разрешен

  • В Java нельзя вызывать super (). Super () .. Дети имеют доступ к своим родителям, но не к бабушке и дедушке.

Значит, ты жертва плохого дизайна. РЕДАКТИРОВАТЬ: исправлена ​​опечатка

0 голосов
/ 31 января 2010

Если бы вы могли использовать Scala, вы можете написать

i match {
  case a: A => handlerA(a) 
  case b: B => handlerB(b)
  case _ => throw new Exception("Unknown i: " + i.toString)
}
0 голосов
/ 31 января 2010

Я думаю, что Шаблон адаптера в этом случае более применим, чем Шаблон посетителя.

0 голосов
/ 31 января 2010

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

void dispatch(I i)
{
   if(i instanceof A)
   {
      handlerA();
   } 
   else 
   {
      handlerB();
   }
}

А если серьезно, если вы вообще можете этого избежать, не пишите такой код.Если вы не можете их изменить, можете ли вы случайно расширить A и B, добавить другой метод handler () для обоих и использовать эти новые подклассы вместо A и B?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...