В Kotlin все является объектом, в том числе и функции. И функции, как и другие объекты, имеют определенный тип. Тип функции определяется следующим образом:
(типы_параметров) -> возвращаемый_тип
Возьмем функцию которая не принимает никаких параметров и ничего не возвращает:
fun hello(){ println("Hello Kotlin") }
Она имеет тип
() -> Unit
Если функция не принимает параметров, в определении типа указываются пустые скобки. Если не указан возвращаемый тип, то фактически а в качестве типа возвращаемого значения
применяется тип Unit
.
Возьмем другую функцию:
fun sum(a: Int, b: Int): Int{ return a + b }
Эта функция принимает два параметра типа Int и возвращает значение типа Int, поэтому она имеет тип
(Int, Int) -> Int
Что дает нам знание типа функции? Используя тип функции, мы можем определять переменные и параметры других функций, которые будут представлять функции.
Переменная может представлять функцию. С помощью типа функции можно определить, какие именно функции переменная может представлять:
fun main() { val message: () -> Unit message = ::hello message() } fun hello(){ println("Hello Kotlin") }
Здесь переменная message
представляет функцию с типом () -> Unit
, то есть функцию без параметров, которая ничего не возвращает.
Далее определена как раз такая функция - hello()
, соответственно мы можем передать функцию hello переменной message.
Чтобы передать функцию, перед названием функции ставится оператор ::
message = ::hello
Затем мы можем обращаться к переменной message()
как к обычной функции:
message()
Так как переменная message ссылается на функцию hello, то при вызове message()
фактически будет вызываться функция hello()
.
При этом тип функции также может выводится исходя из присваемого переменной значения:
val message = ::hello // message имеет тип () -> Unit
Рассмотрим другой пример, когда переменная ссылается на функцию с параметрами:
fun main() { val operation: (Int, Int) -> Int = ::sum val result = operation(3, 5) println(result) // 8 } fun sum(a: Int, b: Int): Int{ return a + b }
Переменная operation представляет функцию с типом (Int, Int) -> Int
, то есть функцию с двумя параметрами типа Int и возвращаемым значением типа Int.
Соответственно такой переменной мы можем присвоить функцию sum
, которая соответствует этому типу.
Затем через имя переменной фактически можно обращаться к функции sum()
, передавая ей значения для параметров и получая ее результат:
val result = operation(3, 5)
При этом динамически можно менять значение, главное чтобы оно соответствовало типу переменной:
fun main() { // operation указывает на функцию sum var operation: (Int, Int) -> Int = ::sum val result1 = operation(14, 5) println(result1) // 19 // operation указывает на функцию subtract operation = ::subtract val result2 = operation(14, 5) println(result2) // 9 } fun sum(a: Int, b: Int): Int{ return a + b } fun subtract(a: Int, b: Int): Int{ return a - b }