Полиморфизм Java - Выбор правильного метода на основе подтипа - PullRequest
3 голосов
/ 20 мая 2010

С учетом следующих сигнатур классов и уровней обслуживания:

public class PersonActionRequest {
    PersonVO person
    // ... other fields
}
public class MyServiceLayerClass {

   public void requestAction(PersonActionRequest request)
   {
       PersonVO abstractPerson = request.getPerson();
       // call appropriate executeAction method based on subclass of PersonVO
   }
   private void executeAction(PersonVO person) {}
   private void executeAction(EmployeeVO employee) {}
   private void executeAction(ManagerVO manager) {}
   private void executeAction(UnicornWranglerVO unicornWrangler) {}
}

Как обсуждено здесь , java выберет лучший метод на основе информации о типе во время компиляции. (То есть, он всегда будет выбирать executeAction(PersonVO person)).

Какой самый правильный способ выбрать правильный метод?

Интернет говорит мне, что использование instanceof дает мне пощечину. Однако я не вижу подходящего способа выбора метода без явного приведения abstractPerson к одному из других конкретных типов.

РЕДАКТИРОВАТЬ: Чтобы уточнить - Переданный VO представляет собой простой ValueObject, предоставляемый для веб-клиентов для создания экземпляров и передачи. По соглашению у него нет методов, это просто структура данных с полями ,

По этой причине звонить по номеру personVO.executeAction() нельзя.

Спасибо

Marty

Ответы [ 5 ]

4 голосов
/ 20 мая 2010

Если executeAction - это метод в базовом классе или интерфейсе, который является общим для PersonVO, EmployeeVO, ManagerVO и UnicornWranglerVO, вы можете просто вызвать abstractPerson.executeAction() вместо нескольких переопределенных методов.

3 голосов
/ 20 мая 2010

Ваше принципиальное препятствие для полиморфизма здесь, по-видимому, заключается в том, что объект данных 'dumb-struct' + сервисный класс 'manager' «Более полиморфный» подход заключается в том, чтобы execute () был методом, который переопределяют различные реализации человека.

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

public interface PersonVisitor {
   void executeAction(EmployeeVO employee);
   void executeAction(ManagerVO manager);
   void executeAction(UnicornWranglerVO unicornWrangler);
}
public abstract class PersonVO {
public abstract void accept(PersonVisitor visitor);
}
public class EmployeeVO extends PersonVO {
@Override
public void accept(PersonVisitor visitor) {
  visitor.executeAction(this);
}
}

public class MyServiceLayerClass implements PersonVisitor {

   public void requestAction(PersonActionRequest request)
   {
       PersonVO abstractPerson = request.getPerson();
       abstractPerson.accept(this);
   }

   public void executeAction(EmployeeVO employee) {}
   public void executeAction(ManagerVO manager) {}
   public void executeAction(UnicornWranglerVO unicornWrangler) {}
}
2 голосов
/ 20 мая 2010

Шаблон Visitor часто используется для преодоления Java, лишенного двойной диспетчеризации.

2 голосов
/ 20 мая 2010

Вы можете изменить способ подхода к дизайну и использовать Посетитель , передавая исполнителя в Person и указав тип абонента, которому звонить.

0 голосов
/ 20 мая 2010

Я бы явно бросил abstractPerson.Это не только гарантирует, что JVM получает правильный метод, но и делает его намного проще для чтения и гарантирует, что вы знаете, что происходит.

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