Kotlin в IntelliJ IDEA Kotlin змінні Kotlin типи даних Kotlin операції з числами Kotlin умовні вирази Kotlin умовні конструкції Kotlin цикли Kotlin послідовності Kotlin масиви Kotlin функціональне програмування Kotlin змінна кількість параметрів. Vararg Kotlin повернення результату. оператор return Kotlin однорядкові і локальні функції Kotlin перевантаження функцій Kotlin Лямбда-вирази Kotlin функції вищого порядку Kotlin Анонімні функції Kotlin ООП Класи і об'єкти Kotlin ООП властивості Kotlin ООП конструктор Kotlin ООП функції в класах Kotlin ООП Пакети та імпорт Kotlin ООП модифікатори видимості Kotlin ООП вкладені класи Kotlin ООП інтерфейси Kotlin ООП спадкування Kotlin ООП Перевизначення методів і властивостей Kotlin ООП Абстрактні класи та методи Kotlin ООП Data-класи Kotlin ООП перерахування enums Kotlin ООП Null і nullable-типи Kotlin ООП Обробка винятків Kotlin ООП перетворення типів Kotlin ООП Інфіксна функція Kotlin ООП функції розширення Kotlin ООП Узагальнені класи і функції Kotlin ООП обмеження узагальнень Kotlin ООП Варіантність, коваріантність і контраваріантність Kotlin Колекції. Змінювані і незмінні колекції Kotlin Колекції. LIST список Kotlin Колекції. Set Kotlin Колекції. Map

Kotlin функції вищого порядку


Функції вищого порядку (high order function) - це функції, які або беруть функцію як параметр, або повертають функцію, або і те, і інше.


Тип функції

Для визначення функцій високого порядку насамперед необхідно уявляти, що таке тип функції. Тип функції визначається наступним чином:

(типы_параметров) -> возвращаемый_тип

Наприклад, візьмемо наступне лямбда-вираз:

{mes:String-> println(mes)}

Це лямбда-вираз приймає як параметр рядок і формально нічого не повертає (точніше повертається типом є Unit). Тому тип цього виразу буде наступний:

(String)-> Unit

Інший приклад: лямбда-вираз приймає два числа і повертає їх суму:

x: Int, y: Int -> x+y

Цей вислів матиме наступний тип:

(Int, Int) -> Int

Якщо лямбда-вираз не приймає ніяких параметрів, то вказуються порожні дужки:

() -> Unit

Наприклад, цього типу буде відповідати лямбда-вираз {println("hello")}

При визначенні лямбда-вирази і присвоєння його змінної ми можемо явно у цій змінній вказати тип:

val sum: (Int, Int)-> Int = {x:Int, y: Int -> x+y}
val printer: (String) -> Unit = {message: String -> println(message)}

Правда, в даному випадку тип можна не вказувати, так як компілятор може сам вивести тип змінної.


Передача лямбда-вирази в функцію

Для передачі лямбда-вирази в функцію, необхідно визначити у функції параметр, тип якого відповідає типу лямбда-вирази:

fun main(args: Array<String>) {
 
    val add = {x:Int, y: Int -> x+y}
    val multiply = {x:Int, y: Int -> x*y}
 
    action(5, 3, add)
    action(5, 3, multiply)
    action(5, 3, {x: Int, y: Int -> x -y})
}
 
fun action (n1: Int, n2: Int, operation: (Int, Int)-> Int){
    val result = operation(n1, n2)
    println(result)
}

В даному випадку функція action визначає три параметри. Перший два параметра - числа, а третій параметр - деяка операція, яка проводиться над цими числами. На момент визначення функції можна не знати, що це буде за операція. Це можливо будь-лямбда-вираз, яке приймає два об'єкти типу Int і повертає також об'єкт типу Int.

У самій функції action викликаємо цю операцію, передаючи їй два числа, і отриманий результат виводимо на консоль.

При виконанні функції action ми можемо передати для його третього параметра лямбда-вираз, яке відповідає цим параметром за типом:

action(5, 3, add)
action(5, 3, multiply)
action(5, 3, {x: Int, y: Int -> x -y})

Повернення функції з функції

У більш рідкісних випадках може знадобитися повернути функцію з іншої функції. В цьому випадку для функції в якості повертається типу встановлюється тип іншої функції. А в тілі функції повертається лямбда вираз. наприклад:

fun selectAction(key: Int): (Int, Int) -> Int{
    // определение возвращаемого результата
    when(key){
        1 -> return {x:Int, y: Int -> x + y}
        2 -> return {x:Int, y: Int -> x - y}
        3 -> return {x:Int, y: Int -> x * y}
        else -> return  {x:Int, y: Int -> 0}
    }
}

Тут функція selectAction приймає один параметр - key, який представляє тип Int. Як повертається типу у функції зазначений тип (Int, Int) -> Int . Тобто selectAction буде повертати якусь функцію, яка приймає два параметри типу Int і повертає об'єкт типу Int.

У тілі функції selectAction в залежності від значення параметра key повертається певний лямбда-вираз, яке відповідає типу (Int, Int) -> Int .

Використовуємо цю функцію:

fun main(args: Array<String>) {
 
    var action = selectAction(1)
    println(action(8,5))    // 13
 
    action = selectAction(2)
    println(action(8,5))    // 3
 
}
fun selectAction(key: Int): (Int, Int) -> Int{
    // определение возвращаемого результата
    when(key){
        1 -> return {x:Int, y: Int -> x + y}
        2 -> return {x:Int, y: Int -> x - y}
        3 -> return {x:Int, y: Int -> x * y}
        else -> return  {x:Int, y: Int -> 0}
    }
}

Тут змінна action зберігає результат функції selectAction. Так як selectAction повертає лямбда-вираз, то і змінна action буде зберігати певний лямбда-вираз. Потім через змінну action можна викликати це лямбда-вираз. Оскільки лямбда-вираз відповідає типу (Int, Int) -> Int , то при його виклику йому необхідно передати два числа і відповідно ми можемо отримати його результат і вивести його на консоль.


Наш партнер:
beta test mp3 playlist downloader