При реализации универсального интерфейса всегда следует указывать аргументы типа. Вы можете обойтись без их указания, но тогда вы будете использовать необработанные типы, чего вы не должны.
Когда вы указываете их в делать, вам также необходимо указать их действительным образом.
Первый вариант неверен по двум причинам:
K extends Comparable<K>
неверна.K
и V
нигде не определены.Второй вариант неверен, потому что вы переписали границы на K
. Эта опция отличается от первой тем, что здесь определены K
и V
находятся - K
и V
являются аргументами типа Son
.
Третий вариант компилируется, но использует необработанные типы, что в первую очередь противоречит цели использования дженериков.
В идеале вы должны написать что-то вроде:
class Son<K extends Comparable<K>, V> implements Father<K, V> {
}
Обратите внимание, как я не переписывал границы и определил K
и V
как аргументы типа для Son
.
В качестве альтернативы укажите конкретный тип:
class Son implements Father<String, Integer> {
}
Что касается первого, которое вы опубликовали, может ли компилятор не сделать вывод о K из определения интерфейса, в котором явно уже есть вся информация, необходимая для класса? Почему вам нужно снова написать границу, K расширяет сопоставимые вещи, а не просто K для класса?
@AungKhant Именно поэтому вы не должна переписываете привязку.
Последний, похоже, не показывает ошибки, но я боюсь, что могу ошибиться, не зная точно правильный. А также, похоже, есть еще один действительный (без красного выделения в IDE), который я не могу вспомнить. Что бы вы написали на моем месте?