Функции высокого порядка (high order function) - это функции, которые либо принимают функцию в качестве параметра, либо возвращают функцию, либо и то, и другое.
Чтобы функция могла принимать другую функцию через параметр, этот параметр должен представлять тип функции:
fun main() { displayMessage(::morning) displayMessage(::evening) } fun displayMessage(mes: () -> Unit){ mes() } fun morning(){ println("Good Morning") } fun evening(){ println("Good Evening") }
В данном случае функция displayMessage()
через параметр mes
принимает функцию типа () -> Unit
, то есть такую функцию,
которая не имеет параметров и ничего не возвращает.
fun displayMessage(mes: () -> Unit){
При вызове этой функции мы можем передать этому параметру функцию, которая соответствует этому типу:
displayMessage(::morning)
Рассмотрим пример параметра-функции, которая принимает параметры:
fun main() { action(5, 3, ::sum) // 8 action(5, 3, ::multiply) // 15 action(5, 3, ::subtract) // 2 } fun action (n1: Int, n2: Int, op: (Int, Int)-> Int){ val result = op(n1, n2) println(result) } fun sum(a: Int, b: Int): Int{ return a + b } fun subtract(a: Int, b: Int): Int{ return a - b } fun multiply(a: Int, b: Int): Int{ return a * b }
Здесь функция action
принимает три параметра. Первые два параметра - значения типа Int. А третий параметр представляет функцию, которая имеет тип
(Int, Int)-> Int
, то есть принимает два числа и возвращает некоторое число.
В самой функции action вызываем эту параметр-функцию, передавая ей два числа, и полученный результат выводим на консоль.
При вызове функции action мы можем передать для ее третьего параметра конкретную функцию, которая соответствует этому параметру по типу:
action(5, 3, ::sum) // 8 action(5, 3, ::multiply) // 15 action(5, 3, ::subtract) // 2
В более редких случаях может потребоваться возвратить функцию из другой функции. В этом случае для функции в качестве возвращаемого типа устанавливается тип другой функции. А в теле функции возвращается лямбда выражение. Например:
fun main() { val action1 = selectAction(1) println(action1(8,5)) // 13 val action2 = selectAction(2) println(action2(8,5)) // 3 } fun selectAction(key: Int): (Int, Int) -> Int{ // определение возвращаемого результата when(key){ 1 -> return ::sum 2 -> return ::subtract 3 -> return ::multiply else -> return ::empty } } fun empty (a: Int, b: Int): Int{ return 0 } fun sum(a: Int, b: Int): Int{ return a + b } fun subtract(a: Int, b: Int): Int{ return a - b } fun multiply(a: Int, b: Int): Int{ return a * b }
Здесь функция selectAction
принимает один параметр - key, который представляет тип Int
. В качестве возвращаемого типа у
функции указан тип (Int, Int) -> Int
. То есть selectAction
будет возвращать некую функцию, которая принимает два параметра типа Int и возвращает объект типа Int.
В теле функции selectAction в зависимости от значения параметра key возвращается определенная функция, которая соответствует типу (Int, Int) -> Int
.
Далее в функции main
определяется переменная action1
хранит результат функции selectAction
. Так как
selectAction()
возвращает функцию, то и переменная action1 будет хранить эту функцию. Затем через переменную action1 можно вызвать эту функцию.
Поскольку возвращаемая функция соответствует типу (Int, Int) -> Int
, то при вызове в action1
необходимо передать
два числа, и соответственно мы можем получить результат и вывести его на консоль.