Возвращение значения и переходы
В Kotlin имеется три выражения структурного перехода:
returnпо умолчанию возвращается из ближайшей функции или анонимной функции.breakзавершает ближайщий цикл.continueпереходи к следующему шагу ближайщего цикл.
Все эти выражения могут использоваться как часть более крупных выражений:
val s = person.name ?: return
тип этих выражений является тип Nothing.
Метки break и continue
Либое выражение в Kotlin может быть отмечено меткой. Метки имееют форму идентификатора после которого следует символ @. Например bc@, fooBar@ являются валидными метками. Чтобы отметить меткой выражение мы просто помещаем метку перед его началом.
loop@ for (i in 1..100) {
// ...
}
Теперь мы можем определить break и continue меткой
loop@ for (i in 1..100) {
for (j in 1..100) {
if (...) break@loop
}
}
break с меткой переходит в точку выполнения находящейся сразу после цикла, отмеченного этой меткой.
continue переходит к следующей итерации этого цикла.
Возврат к метке
С помощью функциональных литералов, локальных функций и object выражений, в Kotlin языке функции могут быть вложенными.
return позволяет нам вернуться из внешней функции.
Наиболее самым важным вариантом использования является возврат из лямбда-выражения.
Об этом стоит помнить, когда мы пишем подобный код:
fun foo() {
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return // не локальный возврат прямо к месту вызова foo()
print(it)
}
println("this point is unreachable")
}
Выражение return возвращается к ближайщей функции, то есть к foo
Обратите внимание, что такие нелокальные возвращения поддерживаются только для лямбда-выражений, переданных в inline функции.
Если нам нужно вернуться из лямбда выражения, мы должны отметить его меткой и указать в return
fun foo() {
listOf(1, 2, 3, 4, 5).forEach lit@{
if (it == 3) return@lit // локальный возврат к вызову лямбды, то есть к forEach циклу.
print(it)
}
print(" done with explicit label")
}
Теперь мы возвращается только из лямбда выражения. Часто бывает удобнее использовать неявные метки: такая метка имеет то же имя, что и функция, которой передается лямбда.
fun foo() {
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return@forEach // локальный возврат к вызову лямбды, то есть к forEach циклу.
print(it)
}
print(" done with implicit label")
}
В качестве альтернативы мы можем заменить лямбда выражение на анонимну функцию.
Оператор return в анонимной функции будет возвращаться из самой анонимной функции.
fun foo() {
listOf(1, 2, 3, 4, 5).forEach(fun(value: Int) {
if (value == 3) return // локальный возврат к вызову анонимной функции, то есть к forEach циклу.
print(value)
})
print(" done with anonymous function")
}
Обратите внимание, что использование локальных возвратов в предыдущих трех примерах аналогично использованию
continue в обычных циклах. Прямого эквивалента для break нет, но его можно симулировать
добавлением другой вложенной лямбдой и не локальным возвращение из нее.
fun foo() {
run loop@{
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return@loop // не локальный возврат из лямбды переданной в run
print(it)
}
}
print(" done with nested loop")
}
При возврате значения анализатор отдает предпочтение return@
return@a 1
Это означает "вернуть 1 к метке @a", а не "вернуть выражение отмеченное меткой (@a 1)".
Комментарии
Отправить комментарий