#kotlin #generics
#kotlin #дженерики
Вопрос:
В последнее время я экспериментировал с дженериками и нашел хороший пример, где я мог бы их использовать, однако я застрял, и мои поиски не привели к решению, или я неправильно понял. Смотрите ниже пример кода:
open class X()
class Y : X()
class Z : X()
abstract class A<T : X> {
lateinit var one: T
fun setup(
one: T
) {
this.one = one
}
}
class B<T : Y> : A<T>()
class C {
fun initB() {
B<Y>() // Works as intended
B<Z>() // Type argument is not within its bounds
B<X>() // Type argument is not within its bounds
}
}
Я хотел бы иметь ситуацию, при которой доступ one
из class B
type of one
выводится правильно, поэтому, если я создаю экземпляр B
с типом Z
one
, он также будет выводиться как тип Z
. К сожалению, выполнение этого, как я думал, было правильным, приводит к « Type argument is not within its bounds
. Любая помощь была бы весьма признательна.
Комментарии:
1. Не уверен, понимаю ли я вашу проблему.
B<T : Y>
указывает, чтоT
должен быть подтипомY
иX
ниZ
один из них не является.2. Вы просто имели в виду
class B<T : X> : A<T>()
? ОбратитеX
внимание вместоY
. Я думаю, что это соответствовало бы вашим требованиям.
Ответ №1:
Тип B должен быть подтипом Y, как вы его определили B<T : Y>
, но ни X, ни Z не являются подтипом Y. X является супертипом Y, а Z вообще не имеет вертикальной связи с Y.
Даже если бы они были подтипами, вы не смогли бы сделать то, на что надеялись. Поскольку ваш класс имеет T
переменную, T
он должен быть инвариантным, чтобы он работал. Инвариантность означает, что вы не можете неявно изменять тип экземпляра класса вверх и вниз.
Подумайте, как это могло бы сломаться, если бы это позволило вам:
val bY: B<Y> = B<Y>()
val bX: B<X> = bY // not allowed because of invariance
// If it were allowed:
bX.one = X()
val y: Y = bY.one // ClassCastException: cannot cast X to Y