Как передать функцию в качестве параметра в другую функцию в Kotlin?
Использование функциональных типов в Kotlin
В Kotlin функции являются объектами первого класса, и их можно передавать как параметры с помощью функциональных типов. Для вашего примера правильный тип — (Int, Int) -> Int, что означает: "функция, принимающая два Int и возвращающая Int".
fun applyOperation(x: Int, y: Int, operation: (Int, Int) -> Int) {
val result = operation(x, y)
println("Результат: $result")
}
// Использование
val add = { a: Int, b: Int -> a + b }
applyOperation(5, 3, add) // Результат: 8
// Или лямбда напрямую
applyOperation(10, 4) { a, b -> a * b } // Результат: 40
Передача именованной функции
Вы также можете передавать уже определённые функции через ссылку с оператором :::
fun multiply(a: Int, b: Int) = a * b
applyOperation(6, 2, ::multiply) // Результат: 12
Работа с разными сигнатурами
Для функций с другим количеством параметров или возвращаемыми типами используйте соответствующие функциональные типы:
() -> Unit— функция без параметров, ничего не возвращает(String) -> Boolean— принимает строку, возвращает Boolean(Int, Double, String) -> List<Int>— три параметра разных типов, возвращает список
fun executeWithLog(action: () -> Unit) {
println("Начало выполнения")
action()
println("Конец выполнения")
}
executeWithLog { println("Привет!") }
// Вывод:
// Начало выполнения
// Привет!
// Конец выполнения
Функции с nullable-типом
Если функция может быть null, оберните тип в скобки и добавьте вопросительный знак:
fun safeOperation(x: Int, y: Int, operation: ((Int, Int) -> Int)?) {
val result = operation?.invoke(x, y) ?: 0
println("Результат: $result")
}
safeOperation(5, 3, null) // Результат: 0
Практический пример: фильтрация списка
fun filterList(list: List<Int>, predicate: (Int) -> Boolean): List<Int> {
val result = mutableListOf<Int>()
for (item in list) {
if (predicate(item)) result.add(item)
}
return result
}
val numbers = listOf(1, 2, 3, 4, 5, 6)
val evenNumbers = filterList(numbers) { it % 2 == 0 }
println(evenNumbers) // [2, 4, 6]
Дополнительные советы
- Для коротких лямбд используйте неявный параметр
it, если функция принимает один аргумент - Если лямбда — последний параметр, её можно вынести за скобки (trailing lambda)
- Для многострочных лямбд последнее выражение становится возвращаемым значением
Такой подход делает код гибким и читаемым, позволяя легко абстрагировать поведение.
<<Использование typealias для удобства
Если вы часто используете один и тот же функциональный тип, можно задать для него псевдоним с помощью typealias. Это улучшает читаемость кода, особенно в сложных сигнатурах.
typealias IntOperation = (Int, Int) -> Int
fun applyOperation(x: Int, y: Int, operation: IntOperation) {
println(operation(x, y))
}
fun subtract(a: Int, b: Int) = a - b
applyOperation(10, 3, ::subtract) // 7
Функции с несколькими параметрами-функциями
Вы можете передавать несколько функций разного типа:
fun combineResults(
a: Int,
b: Int,
transform: (Int) -> Int,
combine: (Int, Int) -> Int
): Int {
return combine(transform(a), transform(b))
}
val result = combineResults(3, 4, { it * 2 }, { x, y -> x + y })
println(result) // (3*2) + (4*2) = 14
Inline-функции для оптимизации
Если вы передаёте лямбды в функции высшего порядка, Kotlin создаёт анонимные классы, что может повлиять на производительность. Для критичных участков используйте модификатор inline:
inline fun measureTime(action: () -> Unit) {
val start = System.nanoTime()
action()
val end = System.nanoTime()
println("Время: ${end - start} ns")
}
measureTime {
Thread.sleep(100)
}
Это встраивает код лямбды на место вызова, избегая создания объектов. Однако не злоупотребляйте inline для больших функций — это увеличит размер байткода.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги