Мы уже знаем, что все функции в Kotlin являются типами
Это не так.Существуют типы функций, экземпляры типов функций и объявления функций.Это объявление функции, тип возвращаемого значения которой Unit
:
fun p() : Unit
{
println("Hello P")
}
Это тип функции:
() -> Unit
Это объявление функции, тип возвращаемого значения которойтип функции () -> Unit
:
fun y() : () -> Unit =
{
println("Hello Y")
}
В то время как при вызове p()
выполняется оператор print, при этом y()
просто возвращает экземпляр функции, который при вызове выполнит оператор print:
y()()
Структурно, объявление функции очень похоже на объявление свойства с типом функции:
val x: () -> Unit =
{
println("Hello X")
}
Синтаксически вы можете использовать его так же:
x()
Вы также можете передать его другой функции:
fun higherOrderFun(block: () -> Unit) [
println("higher order")
block()
}
higherOrderFun(x)
Но вы не можете сделать то же самое с объявлением функции:
higherOrderFun(p) // Compiler error
Это потому, что объявление функции не«вещь», которую вы можете передать, это просто объявление исполняемого кода.
Вы также можете создать экземпляр типа функции из объявления функции:
::p
Теперь это эквивалентнодо x
.На самом деле, вы также можете написать
val x = ::p
, и теперь у вас есть экземпляр x
, который ничего не делает, но немедленно вызывает p()
и возвращает его значение.
Пока есть сильныйформальная симметрия между объявлениями функций и экземплярами функций, и есть даже языки, которые имеют только последние (например, JavaScript или LISP), первые лучше для производительности и использования памяти.