ColinD почти правильно.Вероятно, вы захотите вот что:
public interface BasedOnOther<T> {
public T getOther();
public void staticSatisfied(BasedList<? extends T> list);
}
Это потому, что аргументы метода ковариантны , но общие шаблоны инвариантны .Посмотрите на этот пример:
public test() {
Number n1;
Integer n2; //Integer extends Number. Integer is a more-specific type of Number.
n1 = n2; //no problem
n2 = n1; //Type mismatch because the cast might fail.
List<Number> l1;
List<Integer> l2;
List<? extends Number> l3;
l1 = l3; //No problem.
l1 = l2; //Type mismatch because the cast might fail.
}
Почему:
Попытка поместить Integer
туда, где принадлежит Number
, является ковариацией, и это обычно правильно для аргументов функции.
Попытка поместить Number
туда, где принадлежит Integer
, является противоположностью, противоположностью, и это обычно правильно для возвращаемых значений функции.Например, если вы определили функцию для возврата числа, она может вернуть целое число.Однако если вы определили его как возвращающее целое число, вы не сможете вернуть число, потому что это может быть, например, число с плавающей точкой.
Когда вы имеете дело с обобщениями, компилятор не может сказатьесли общий параметр (в вашем случае, T) будет ковариантным или контравариантным.Например, в вашем коде T является возвращаемым значением и частью аргумента.По этой причине общие параметры по умолчанию инвариантны.
Если вы хотите ковариации, используйте <? extends T>
.Для контравариантности используйте <? super T>
.Как правило, вы всегда хотите указать ковариацию / контравариантность для всех открытых функций.Для частных функций это не так важно, потому что вы, как правило, уже знаете типы.
Это не относится к Java, другие объектно-ориентированные языки имеют аналогичную проблему.