(Java) Как реализовать метод интерфейса с ограниченным универсальным шаблоном? - PullRequest
2 голосов
/ 18 марта 2012

Я поддерживаю 2 проекта с одинаковыми функциями и объединяю их в общий проект. Я определил интерфейс:

public interface GraphData 
{
    public List<? extends ShapeData> getShapes();
    public void setShapes( List<? extends ShapeData> shapes );
}

Я реализую этот интерфейс в обоих проектах:

public class Graph implements GraphData 
{
     public List<Shape> shapes = new ArrayList<Shape>();

     public List<? extends ShapeData> getShapes() 
     { 
         return shapes;
     }

     public void setShapes( List<? extends ShapeData> shapes )
     {
        this.shapes = shapes;
     }
}

Shape является подтипом ShapeData. Когда я компилирую этот класс, я получаю ошибку о приведении List<Shape> к List<? of... Как мне решить эту ошибку компиляции? Может быть, лучше спросить, нужно ли мне определять методы интерфейса, используя ограниченный подстановочный знак (то есть? Extends)?

Ответы [ 2 ]

8 голосов
/ 18 марта 2012

По сути, ваш интерфейс слишком широкий IMO. Вы указали, что shapes (кстати, публичное поле - почему?) Должно быть List<Shape>. Что бы вы ожидали, если кто-то попадет в неправильный список на setShapes? Например:

public class BadShapeData implements ShapeData { ... }

...

List<BadShapeData> badShapes = new ArrayList<BadShapeData>();
new Graph().setShapes(badShapes);

Это , а не список Shape, не так ли?

Вы можете исправить это, сделав ваш интерфейс универсальным:

public interface GraphData<T extends ShapeData>
{
    List<T> getShapes();
    void setShapes(List<T> shapes);
}

Тогда:

public class Graph implements GraphData<Shape>

В качестве альтернативы вы можете изменить свой интерфейс , а не , чтобы получить установщик. Вам это действительно нужно? Действительно ли интерфейс добавляет много пользы? Разве вы не можете предоставить больше значимых операций над ним, чем просто свойство?

0 голосов
/ 18 марта 2012

Я думаю, это осложнение само по себе. Ваш Graph имеет List<Shape>; получить и установить этот тип, а также.

public interface GraphData 
{
    public List<Shape> getShapes();
    public void setShapes(List<Shape> shapes );
}

У меня обычно нет геттеров / сеттеров в интерфейсах. Это не очень значимое или интересное поведение. Я не согласен, что интерфейс необходим даже для Graph. Возможно, вы захотите подумать о том, чего вы пытаетесь достичь.

...