Некоторое время работал с crossinline inline и noinline, но никогда не понимал crossinline на 100%. Я углубился в чтение и попытался сам сделать несколько примеров кодирования и хотел бы поговорить об одной ситуации.
Таким образом, crossinline отключает возможность добавления возврата к нашей лямбда-функции (поправьте меня, если я ошибаюсь). Давайте посмотрим пример:
inline fun higherOrderFunction(lambda : () -> Unit){
lambda.invoke()
Toast.makeText(this, "test", Toast.LENGTH_SHORT).show()
}
И я вызываю эту функцию так:
higherOrderFunction {
print("E Numbers Detector android app is the best")
return
}
Работает отлично. Имейте в виду, что в этом случае Toast не выполняется из-за вызываемого возврата. Если я поставлю crossinline на свою лямбду:
inline fun higherOrderFunction(crossinline lambda : () -> Unit){.......
Я не смогу использовать return в том месте, где я его поставил. Таким образом, он отключает возврат в лямбда. Но так ли это?
Что, если я сделаю обходной путь и поставлю лямбда-код в какую-то другую функцию и добавлю return:
inline fun higherOrderFunction(lambda : () -> Unit){
lambda.invoke()
Toast.makeText(this, "test", Toast.LENGTH_SHORT).show()
}
Эта часть вверх остается прежней. Но теперь я добавляю функцию:
fun testLambdaFunction() {
print("E Numbers Detector android app is the best")
return
}
И сделать вызов следующим образом:
higherOrderFunction {
testLambdaFunction()
}
Если я это сделаю, все будет работать нормально, Toast будет напечатан, а моя лямбда-функция имеет возврат сама по себе, даже если я использую crossinline, чтобы отключить ее.
Почему это так? Разве этот «возврат» не является частью нашей лямбды, которую мы отправили в качестве параметра?
Когда у вас есть return
в лямбде higherOrderFunction()
, функция, которая «возвращает», — это higherOrderFunction()
, а когда вы return
в testLambdaFunction()
, функция, которая «возвращает», — это просто сама testLambdaFunction()
. Более или менее думайте о crossinline
как о переключателе, позволяющем лямбде преждевременно завершать выполнение вашей вызывающей функции или нет.
Имейте в виду, что вызовы функций с ключевым словом inline
больше не существуют после компиляции. В основном происходит то, что их тело копируется в их предыдущий вызов функции (не совсем так, я немного упрощаю). Имея это в виду, давайте разберем приведенные выше примеры.
inline fun higherOrderFunction(lambda : () -> Unit) {
lambda.invoke()
println("test")
}
fun main() {
higherOrderFunction {
print("E Numbers Detector android app is the best")
return
}
}
Это эквивалентно приведенному ниже коду, если бы мы теоретически могли преобразовать встроенную функцию в код Kotlin.
fun main() {
print("E Numbers Detector android app is the best")
return
println("test")
}
Как вы можете видеть, return
завершает функцию main()
, и поэтому «тест» никогда не печатается.
inline fun higherOrderFunction(crossinline lambda : () -> Unit) {
lambda.invoke()
println("test")
}
fun testLambdaFunction() {
println("E Numbers Detector android app is the best")
return
println("This code is unreachable")
}
fun main() {
higherOrderFunction {
testLambdaFunction()
}
}
Как видите, на этот раз return
заканчивается testLambdaFunction()
, а не main()
.
fun testLambdaFunction() {
println("E Numbers Detector android app is the best")
return
println("This code is unreachable")
}
fun main() {
testLambdaFunction()
println("test")
}
Функция main()
не заканчивается до тех пор, пока не будет напечатан «текст», так как в ней не вызывается return
.
Я немного отредактировал свой ответ, чтобы сделать объяснение более понятным. Дайте мне знать, если есть что-то, что я мог бы уточнить еще больше.
Нет, все нормально, принято!
Да, я это понимаю, но я думаю, что в обоих случаях «возврат» — это часть лямбды, которую мы отправляем, не так ли? Так что определение нас немного сбивает с толку. Ок спасибо за ответ!