Дженерики; аргумент типа не входит в его границы

#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