Почему "возвращение" возвращает "возвращение" в Котлин?
Вопрос может звучать глупо, но в нем нет опечатки.
fun test(): Any {
return return true
}
Это действительно возможно в Котлине. Хотя компилятор предупреждает о
Недоступный код
для внешнего возврата. Но это всего лишь предупреждение.
Я не хочу сравнивать Java с Kotlin, но мне было интересно, будет ли то же самое работать на Java.
public class Test {
// ...
static int test() {
return return 1;
}
}
Это не так!
/Test.java:8: ошибка: незаконный запуск выражения
return return 1;
^
/Test.java:8: ошибка: не утверждение
return return 1;
^
2 ошибки
Почему Котлин разработал этот способ?
Ответы
Ответ 1
return
является выражением в Kotlin, с типом возвращаемого значения Nothing
, типом, который действует как подтип всех других типов. Это позволяет вам, например, делать это безопасным способом и без дополнительных строк null
проверяет:
fun getInt(): Int? = ...
fun printInt() {
val int: Int = getInt() ?: return
println(int)
}
Тип getInt() ?: return
может быть Int
здесь, потому что тот самый близкий общий супертип двух сторон оператора Элвиса, благодаря Nothing
является подтипом Int
.
То же самое относится и к throw
, которое также можно использовать с оператором Elvis
, чтобы указать, что вы хотите отменить выполнение по значению null
, не беспокоясь о типах позже.
Это приводит к нечетной причуде, где такие вещи, как
fun x(): Int {
return return throw return throw throw return 0
}
являются допустимым синтаксисом, потому что тип Nothing
делает каждое из выражений действительным, читаемым справа налево. На самом деле произойдет то, что return 0
будет выполняться, а остальная часть кода никогда не будет достигнута, как предупреждает компилятор.
Ответ 2
Поскольку оператор return
представляет собой выражение, которое возвращает Nothing
. В результате следующее также компилируется:
fun main(args: Array<String>) {
val r = return
}
Это указано в docs:
Kotlin имеет три выражения структурного перехода:
-
return
. По умолчанию возвращается из ближайшей закрывающей функции или анонимной функции. [...]
Все эти выражения могут использоваться как часть более крупных выражений:
val s = person.name ?: return
Тип этих выражений - это тип Nothing
.
Так как Nothing
является подтипом любого другого типа, он обладает способностью делать странные утверждения, например, в вашем вопросе, хотя они кажутся очень неправильными...
На самом деле был забавный разговор в KotlinConf, чтобы посмотреть на интересные вещи, такие как:
fun getText(): String {
val s = return throw return "Hello"
}
println(getText())
//prints "Hello"