Передача в подкласс метода, но с суперклассом в качестве параметра?

У меня есть абстрактный класс Vehicle с 2 реализованными подклассами RedVehicle а также YellowVehicle,

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

поскольку Class в общем, я должен параметризовать его с чем-то, однако параметр в качестве родительского класса Vehicle перестает работать вызывающий код с exampleMethod теперь ожидает тип транспортного средства, а не подкласс RedVehicle или же YellowVehicle,

Я чувствую, что должен быть чистый способ сделать это так, каков был бы правильный способ реализовать функциональность?

NB Я не обязательно должен пройти в Class типа, если есть лучшие предложения, я был бы рад попробовать их.

Телефонный код:

service.exampleMethod(RedVehicle.class);
service.exampleMethod(YellowVehicle.class);

Поля / Метод:

//List of vehicles
//Vehicle has 2 subclasses, RedVehicle and YellowVehicle
private List<Vehicle> vehicles;

//Having <Vehicle> as the Class parameter stops the calling code working
public void exampleMethod(Class<Vehicle> type) 
{
    for(Vehicle v : vehicles)
    {
        if(v.getClass().equals(type))
        {
            //do something
        }
    }
}

4 ответа

Решение

Сделайте это вместо этого:

public <T extends Vehicle> void exampleMethod(Class<T> type) 

Почему вы не используете шаблон посетителя?

Таким образом, вы

  • не нужны жетоны типа
  • пусть динамическая диспетчеризация обрабатывает регистр различий (вместо if(v.getClass().equals(type)))
  • более гибки (следуя OCP)

В деталях:

ваш абстрактный класс Vehicle получает метод accept(Visitor v)с подклассами, реализующими это, вызывая соответствующий метод на v,

public interface Visitor {
  visitRedVehicle(RedVehicle red);
  visitYellowVehicle(YellowVehicle yellow);
}

Использование посетителя:

public class Example {

  public void useYellowOnly() {
    exampleMethod(new Visitor() {
        visitRedVehicle(RedVehicle red) {};
        visitYellowVehicle(YellowVehicle yellow) {
             //...action
        });
  }
  public void exampleMethod(Visitor visitor){
      for(Vehicle v : vehicles) {
          v.accept(visitor);
      }  
  }
}

Я обнаружил, что этот синтаксис работает должным образом:

      public void exampleMethod(Class<? extends Vehicle> type) 

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

В этом случае RevisedExposure является подклассом Exposure. Мне нужно вызвать GetMetadata() со списком любого из них, что приводит к тому же набору результатов.

      private async Task<List<Metadata>> GetMetadata<T>(List<T> exposures) where T : Exposure

Теперь я могу вызвать этот метод из двух мест с разными версиями списка, как это.

      var metadata = await GetExposureMetadata(revisions);

или же

      var metadata = await GetExposureMetadata(exposures);

работает отлично!

Другие вопросы по тегам