Подтвердить что ты не робот

Объявление функции Kotlin: знак равенства перед фигурными скобками

В Kotlin синтаксис объявления функции позволяет вам писать знак равенства перед фигурными фигурными скобками. Рассмотрим эти два примера:

  • Без знака =:

    fun foo() {
        bar()
        println("baz")
    }
    

    Код внутри тела запускается путем вызова foo().

  • С знаком =:

    fun foo() = {
        bar()
        println("baz")
    }
    

    Здесь, когда вызывается foo(), ничего не происходит, но чтобы получить выполненное тело, можно написать foo()().

В чем разница в этих двух объявлениях и , почему они ведут себя по-другому?


Этот вопрос, хотя и не имеет большого значения, преднамеренно задан и ответил автору, потому что несколько вопросов уже опубликованы, где люди получили проблемы из-за неправильного определения функций.
4b9b3361

Ответ 1

Несмотря на визуальное сходство, идея этих двух объявлений совершенно другая.

  • Объявление функции без знака равенства - это Unit -returning function (аналогично функциям Java void).

    Что внутри фигурных скобок - это тело, которое выполняется непосредственно над вызовом функции. Функция может быть переписана с помощью Unit явно заданной:

    fun foo(): Unit {
        bar()
        println("baz")
        return Unit
    }
    

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

  • Объявление функции с символом равенства - это функция однократного выражения, и то, что она делает, просто возвращает то, что справа равно знаку.

    Простейший пример: fun getInt() = 1 - это только более короткая форма fun getInt(): Int { return 1 }.

    В foo выражение lambda, и оно возвращается только, не выполнено.

    Тип возврата foo есть () -> Unit, сама функция, и, следовательно, foo является функцией более высокого порядка.

    Без синтаксического сахара и с явным типом foo можно переписать как

    fun foo(): () -> Unit {
        val result: () -> Unit = { bar(); println("baz") }
        return result
    }
    

    Что касается использования, функция, возвращаемая foo, может быть сохранена в переменной, переданной вокруг, и может быть позже вызвана:

    val f = foo()
    
    f() //equivalent to
    f.invoke()
    

    Вот почему foo()() в примере выполняет код из тела лямбда.