Как преобразовать список объектов в список интерфейсов?

У меня есть класс, который работает с интерфейсами:

Вот интерфейс:

public interface Orderable
{
    int getOrder()
    void setOrder()
}

Вот рабочий класс:

public class Worker
{
   private List<Orderable> workingList;

   public void setList(List<Orderable> value) {this.workingList=value;}

   public void changePlaces(Orderable o1,Orderable o2)
   {
     // implementation that make o1.order=o2.order and vice versa
   }
}

Вот объект, реализующий интерфейс:

public class Cat implements Orderable
{
    private int order;

    public int getOrder()
    {
      return this.order;
    }

    public void setOrder(int value)
    {
      this.order=value;
    }

    public Cat(String name,int order)
    {
       this.name=name;
       this.order=order;
    }
}

В основной процедуре я создаю список кошек. Я использую застекленные списки для динамического обновления элементов управления при изменении списка и при создании модели элемента управления с этим списком.

Цель состоит в том, чтобы передать этот список рабочему объекту, чтобы я мог добавить нового кота в список в основной процедуре, и рабочий будет знать об этом, не устанавливая снова свойство списка (список - это тот же объект в основной процедуре и в рабочий). Но когда я звоню worker.setList(cats), он предупреждает о том, что ожидаю выполнения заказа, но получаю Cat ... но Cat реализует возможность заказа. Как мне решить эту проблему?

Вот основной код:

void main()
{
   EventList<Cat> cats=new BasicEventList<Cat>();

   for (int i=0;i<10;i++)
   {
      Cat cat=new Cat("Maroo"+i,i);
      cats.add(cat);
   }

   Worker worker=new Worker(); 
   worker.setList(cats); // wrong!
   // and other very useful code
}

person Artyom Chernetsov    schedule 27.09.2011    source источник


Ответы (4)


Вам нужно изменить класс Worker, чтобы он принимал List<? extends Orderable>

public class Worker
{
   private List<? extends Orderable> workingList;

   public void setList(List<? extends Orderable> value) {this.workingList=value;}

   public void changePlaces(Orderable o1,Orderable o2)
   {
     // implementation that make o1.order=o2.order and vice verca  
   }
}
person Saintali    schedule 27.09.2011
comment
Этот подход сработал для меня лучше всего, поскольку мне нужно было изменить только сигнатуру метода Worker, а не объявление массива, которого я не хотел трогать во всех своих файлах. ИМО более осуществимый подход, чем предложенный Мэттом Боллом ответ - person Makibo; 09.08.2013

Если вам действительно нужна новая коллекция типа интерфейса. Когда, например, вы не владеете методами, которые вызываете.

//worker.setList(cats); 
worker.setList( new ArrayList<Orderable>(cats)); //create new collection of interface type based on the elements of the old one
person Konstantin    schedule 18.11.2014


void main()
{
    EventList<Orderable> cats = new BasicEventList<Orderable>();

    for (int i=0;i<10;i++)
    {
        Cat cat=new Cat("Maroo"+i,i);
        cats.add(cat);
    }

    Worker worker=new Worker(); 
    worker.setList(cats); // should be fine now!
    // and other very usefull code
}

В большинстве случаев просто создайте список Orderables сразу, поскольку cat реализует Orderable, вы сможете добавить кошку в список.

примечание: это я быстро угадываю

person elsom25    schedule 27.09.2011