Можно ли возвращать тот же тип, что и параметр типа, когда оператор

Например:

fun <T> f(a: T): T = when (a) { a is Int -> 0 // if T is Int, then return Int a is String -> "" // if T is String, then return String else -> throw RuntimeException() // Otherwise, throw an exception so that the return type does not matter. } 

Это дает ошибки компиляции:

 Error:(3, 20) The integer literal does not conform to the expected type T Error:(4, 23) Type mismatch: inferred type is String but T was expected 

Затем вы можете передать результат в T Вы не получите никакой помощи компилятора, и вы получите предупреждения, но, по крайней мере, он скомпилирует:

 fun <T> f(a: T): T = when { a is Int -> 0 // if T is Int, then return Int a is String -> "" // if T is String, then return String else -> throw RuntimeException() // Otherwise, throw an exception so that the return type does not matter. } as T 

Обратите внимание, что when (a) здесь нет необходимости, просто, when { достаточно.

В настоящее время, когда компилятор Kotlin анализирует функцию, он не принимает определенных частных случаев параметра типа для частей тела.

Вместо этого код, который работает с параметром типа T , должен быть правильным с любым T Возвращение Int где T ожидается, не считается безопасным только потому, что оно недостаточно аналитично, чтобы доказать, что T всегда является супертипом Int если функция достигает этой ветви.

Один из вариантов заключается в том, чтобы сделать непроверенный приведение к T , как в ответе @ nhaarman, тем самым выражая, что вы уверены, что типы верны.

Другое решение состоит в том, чтобы несколько перегрузок вашей функции работали с разными типами:

 fun f(a: Int) = 1 fun f(a: String) = "" fun f(a: Any): Nothing = throw RuntimeException() 

В этом случае компилятор выберет перегрузку функции на основе аргумента, который вы передаете, в отличие от специализации одной общей функции для определенного аргумента типа, и это более простая задача для компилятора, поскольку она не включает анализ типа внутри тела функции.


Кроме того, аналогичный вопрос:

  • Параметр типа Ketlin reified не используется

  • Почему в этой ситуации не управляется smart-cast?