Не может ссылаться на универсальный тип из ограниченной подстановочной ссылки - PullRequest
0 голосов
/ 22 января 2012

Что не так с Class A ниже, что не позволяет его компилировать?

public class GenericsHell {
   interface Shape{} 
   interface Circle extends Shape {} 

   interface ShapeHelper<T extends Shape> {
      void draw(T shape);
   }

   class A<T extends Shape> {
      A(T shape, ShapeHelper<? extends Shape> helper) {
         helper.draw(shape); // Issues not-applicable argument error 
      }
   }

   class B {
      B(Circle circle, ShapeHelper<Circle> helper) {
         helper.draw(circle);
      }
   }
}   

Eclipse выдает следующую ошибку:

The method draw(capture#1-of ? extends Shape) in the type ShapeHelper<capture#1-of ? extends Shape> is not applicable for the arguments (T)

Ответы [ 5 ]

3 голосов
/ 22 января 2012

Вы определили свой универсальный параметр для класса A как одну вещь, но затем попытались использовать его несовместимым образом в своем конструкторе (<T extends Shape> - это не то же самое, что <? extends Shape>. Чтобы ваш код для компиляции изменил егочтобы последовательно использовать уже определенный вами универсальный параметр:

class A<T extends Shape> {
    public A(T shape, ShapeHelper<T> helper) {
        helper.draw(shape);
    }
}

Кроме того, ваш код не генерирует сообщение об ошибке, которое вы показали в своем вопросе. Скорее это будет что-то вроде этого:

Метод draw (захват # 1-of? Extends GenericsHell.Shape) в типе GenericsHell.ShapeHelper не применим для аргументов (T)

2 голосов
/ 22 января 2012

Метод draw (capture # 1-of? Extends GenericsHell.Shape) в типе GenericsHell.ShapeHelperнеприменимо для аргументов (T)

Проблема в том, что в вашем объявлении фигура имеет тип T, но вы запрашиваете ShapeHelper типаэто означает, что в качестве аргумента можно передать ShapeHelper, где S и T различны.

Затем вы бы вызвали helper<S>.draw(shape<T>);, что не имеет смысла.

Правильная реализация для этого метода будетbe:

class A<T extends Shape> {
  A(T shape, ShapeHelper<T> helper) {
    helper.draw(shape); 
  }
}

, который гарантирует, что форма и помощник по фигуре имеют совместимые типы.

1 голос
/ 22 января 2012

Было бы важно увидеть ваш звонок на A.Но похоже, что вы сделали что-то вроде A<Integer>.Но T должен расширять Shape в соответствии с объявлением вашего класса .. а Integer - нет.Поэтому измените <? extends Shape> на <T> или укажите тип от Shape до A

0 голосов
/ 23 января 2012

Помните, что PECS (производитель extends, потребитель super).

helper - это потребитель (вы передаете ему что-то), следовательно, он не может быть extends.Возможно, это может быть super, но я не знаю, имеет ли это смысл в этом случае

0 голосов
/ 22 января 2012

Попробуйте вместо этого:

class A<T extends Shape> {
    A(T shape, ShapeHelper<T> helper) {
        helper.draw(shape);
    }
}
...