Kotlin: отключенное приведение в моей функции generi c - PullRequest
1 голос
/ 30 мая 2020

Я пытаюсь объединить две свои функции в одну, используя дженерики.

fun <T> List<T>.toElementOrSize1(keySelector: (T) -> String): String {
    val key = keySelector(first())
    return if (all { keySelector(it) == key }) key else "size = $size"
}

fun <T> List<T>.toElementOrSize2(keySelector: (T) -> String?): String? {
    val key = keySelector(first())
    return if (all { keySelector(it) == key }) key else "size = $size"
}

Я мог бы написать это:

fun <T, K : String?> List<T>.toElementOrSize(keySelector: (T) -> K): K {
    val key = keySelector(first())
    return if (all { keySelector(it) == key }) {
        key
    } else {
        "size = $size" as K
    }
}

Это работает, но у меня не отмечен cast warning.

Почему было выдано это предупреждение? И как избежать этого предупреждения?

Спасибо.

1 Ответ

1 голос
/ 30 мая 2020

Компилятор недостаточно сложен, чтобы увидеть, что единственными возможными типами для K являются String и String? (поскольку String является окончательным), поэтому для компилятора K может быть другим подтипом String?, поэтому приведение буквального String может быть небезопасным. А поскольку K - это общий тип c, приведение типов не проверяется из-за стирания типа.

Есть ряд ситуаций, подобных этой, которые возникают при работе с универсальными типами. Это не означает, что вы обязательно сделали что-то не так, просто компилятор не знает достаточно, чтобы быть уверенным, что это не так. Вы можете использовать @Suppress("UNCHECKED_CAST") перед функцией или оператором, чтобы удалить предупреждение и подтвердить, что вы знаете, что это безопасное приведение. Это не значит, что вы делаете что-то взломанное или плохо спроектированное. Он используется несколько раз в исходном коде стандартной библиотеки.

...