Android kotlin crossinline возвращается из лямбда

Некоторое время работал с 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, чтобы отключить ее.

Почему это так? Разве этот «возврат» не является частью нашей лямбды, которую мы отправили в качестве параметра?

0
0
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Когда у вас есть return в лямбде higherOrderFunction(), функция, которая «возвращает», — это higherOrderFunction(), а когда вы return в testLambdaFunction(), функция, которая «возвращает», — это просто сама testLambdaFunction(). Более или менее думайте о crossinline как о переключателе, позволяющем лямбде преждевременно завершать выполнение вашей вызывающей функции или нет.

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

~ встроенный пример https://pl.kotl.in/VCwMsea_n
inline fun higherOrderFunction(lambda : () -> Unit) {
    lambda.invoke()
    println("test")
}
 
fun main() {
    higherOrderFunction {
        print("E Numbers Detector android app is the best")
        return
    }
}

Это эквивалентно приведенному ниже коду, если бы мы теоретически могли преобразовать встроенную функцию в код Kotlin.

~ деконструированный встроенный пример https://pl.kotl.in/rbXgSnBlQ
fun main() {
    print("E Numbers Detector android app is the best")
    return    
    println("test")
}

Как вы можете видеть, return завершает функцию main(), и поэтому «тест» никогда не печатается.

~ перекрестный пример https://pl.kotl.in/bJdEm8QbR
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().

~ деконструированный кроссинлайн пример https://pl.kotl.in/6R3K7P21D
fun testLambdaFunction() {
    println("E Numbers Detector android app is the best")
    return
    println("This code is unreachable")
} 
 
fun main() {
    testLambdaFunction()
    println("test")
}

Функция main() не заканчивается до тех пор, пока не будет напечатан «текст», так как в ней не вызывается return.

Да, я это понимаю, но я думаю, что в обоих случаях «возврат» — это часть лямбды, которую мы отправляем, не так ли? Так что определение нас немного сбивает с толку. Ок спасибо за ответ!

Kratos 08.01.2023 10:56

Я немного отредактировал свой ответ, чтобы сделать объяснение более понятным. Дайте мне знать, если есть что-то, что я мог бы уточнить еще больше.

rtsketo 08.01.2023 20:23

Нет, все нормально, принято!

Kratos 08.01.2023 21:03

Другие вопросы по теме