Как передать функцию как параметр?
В Kotlin можно передавать функции как параметры в другие функции, потому что функции в языке являются «первоклассными объектами» (first-class citizens). Это значит, что их можно сохранять в переменные, передавать в качестве аргументов и возвращать из других функций.
Объявление функции, принимающей функцию в качестве параметра
Функции передаются с помощью функциональных типов. Синтаксис:
fun имяФункции(параметр: (типы_параметров) -> возвращаемый_тип) {
// тело
}
Пример:
fun operate(x: Int, y: Int, operation: (Int, Int) -> Int): Int {
return operation(x, y)
}
Здесь operation — это функция, принимающая два Int и возвращающая Int.
Вызов функции с передачей lambda
Вы можете передать lambda-выражение напрямую:
val result = operate(10, 5) { a, b -> a + b } // 15
Или определить lambda заранее:
val multiply = { a: Int, b: Int -> a \* b }
val result = operate(4, 5, multiply) // 20
Использование обычных функций как аргументов
Можно передавать именованные функции:
fun subtract(a: Int, b: Int): Int = a - b
val result = operate(10, 3, ::subtract) // 7
::subtract — это ссылка на функцию (function reference).
Пример с функцией без параметров
fun greet(action: () -> Unit) {
action()
}
fun sayHello() {
println("Hello!")
}
greet(::sayHello) // передаём ссылку на функцию
greet { println("Hi!") } // передаём lambda
Пример с возвращающим значением
fun processString(str: String, processor: (String) -> String): String {
return processor(str)
}
val upper = processString("kotlin") { it.uppercase() } // "KOTLIN"
Пример с несколькими параметрами
fun combine(a: String, b: String, combiner: (String, String) -> String): String {
return combiner(a, b)
}
val result = combine("Kotlin", "Rocks") { first, second -> "$first $second!" } // "Kotlin Rocks!"
Ссылки на методы и функции (function references)
Можно передавать методы классов и объектов через :::
fun printNumber(n: Int) {
println("Number: $n")
}
val numbers = listOf(1, 2, 3)
numbers.forEach(::printNumber)
Функции как переменные
Можно сохранять функции в переменные и использовать позже:
val add: (Int, Int) -> Int = { x, y -> x + y }
println(add(2, 3)) // 5
Можно использовать и ссылку на функцию:
fun divide(a: Int, b: Int): Int = a / b
val divOp: (Int, Int) -> Int = ::divide
println(divOp(10, 2)) // 5
Inline-функции и лямбда с возвращением
Если вы передаёте функцию как аргумент и хотите использовать return из неё — стоит использовать inline:
inline fun doIfTrue(condition: Boolean, action: () -> Unit) {
if (condition) action()
}
doIfTrue(true) {
println("Executed")
}
Без inline использовать return в лямбде, которая завершает внешнюю функцию, запрещено.
Типы параметров-функций
Функции можно типизировать:
-
() -> Unit — без параметров, ничего не возвращает
-
(Int) -> String — один Int, возвращает String
-
(String, Int) -> Boolean — два параметра, возвращает Boolean
Пример функции, принимающей такую сигнатуру:
fun check(value: String, condition: (String) -> Boolean): Boolean {
return condition(value)
}
val result = check("test") { it.length > 3 } // true
Передача функции как параметра в класс
Можно использовать лямбды в конструкторах:
class Task(val action: () -> Unit) {
fun run() = action()
}
val task = Task { println("Running task") }
task.run()
Тип с nullable-функцией
Иногда функция может быть опциональной:
fun executeIfNotNull(action: (() -> Unit)?) {
action?.invoke()
}
Пример: использование функций как параметров для фильтрации
fun filterList(list: List<Int>, predicate: (Int) -> Boolean): List<Int> {
return list.filter(predicate)
}
val filtered = filterList(listOf(1, 2, 3, 4, 5)) { it % 2 == 0 } // \[2, 4\]
В Kotlin функция может быть передана в качестве параметра в любом контексте: в функцию, в класс, в конструктор, в коллекцию, в качестве события или callback'а. Это позволяет строить гибкие и декларативные API.