Шаг 57.
Основы Kotlin.
Анонимные функции и функциональные типы. Ссылка на функцию

    На этом шаге мы рассмотрим их использование при передаче аргументов в функцию.

    До этого момента вы объявляли лямбды для передачи в аргументе другой функции. Сделать это можно иначе: передать ссылку на функцию. Ссылка на функцию преобразует именованную функцию (функцию, объявленную с ключевым словом fun) в значение, которое можно передавать как аргумент. Ссылку на функцию можно использовать везде, где допускается лямбда-выражение.

    Чтобы увидеть ссылку на функцию, объявите новую функцию и дайте ей имя printConstructionCost.

.   .   .   .   .
inline fun runSimulation(playerName: String, greetingFunction: (String, Int) -> 
    String) {
        val numBuildings = (1..3).shuffled().last() // Случайно выберет 1, 2 или 3
        println(greetingFunction(playerName, numBuildings))
}

fun printConstructionCost(numBuildings: Int) {
    val cost = 500
    println("construction cost: ${cost * numBuildings}")
}


Рис.1. Объявление функции printConstructionCost() (SimVillage.kt)

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

inline fun runSimulation(playerName: String,
                         costPrinter: (Int) -> Unit,
                         greetingFunction: (String, Int) -> String) {
        val numBuildings = (1..3).shuffled().last() // Случайно выберет 1, 2 или 3
        costPrinter(numBuildings)
        println(greetingFunction(playerName, numBuildings))
}


Рис.2. Добавление параметра costPrinter (SimVillage.kt)

    Чтобы получить ссылку на функцию, используйте оператор :: с именем этой функции. Получите ссылку на функцию printConstructionCost и передайте ее как аргумент для нового параметра costPrinter в runSimulation().

fun main() {
    runSimulation("Guyal", ::printConstructionCost) { playerName, numBuildings ->
        val currentYear = 2021 
        println("Adding $numBuildings houses")
        "Welcome to SimVillage, $playerName! (copyright $currentYear)"
    }
}
Файл с проектом можно взять здесь.


Рис.3. Передача ссылки на функцию (SimVillage.kt)

    Запустите SimVillage.kt. Вы увидите, что в дополнение к количеству зданий теперь выводится и суммарная цена затрат на их строительство (рисунок 4).


Рис.4. Результат работы приложения

    Ссылки на функцию полезны в ряде ситуаций. Если у вас есть именованная функция, которая соответствует параметру с типом функции, то вместо объявления лямбды можно использовать ссылку на функцию. Или, может быть, вы захотите передать в аргументе функцию из стандартной библиотеки.

    На следующем шаге мы рассмотрим тип функции как возвращаемый тип.




Предыдущий шаг Содержание Следующий шаг