- Определять функцию с параметрами и типом возвращаемого значения
- Использовать значения по умолчанию, именованные аргументы и функции из одного выражения
- Добавлять функции-расширения к существующим типам
- Писать лямбду и передавать её в функцию высшего порядка
Представь, что в десяти местах программы ты собираешь один и тот же текст приветствия. Когда текст понадобится изменить, придётся исправлять десять мест! Функция позволяет написать код один раз, дать ему имя и вызывать сколько угодно раз. Ты уже работал с функциями: main, println и repeat — это функции. Теперь ты создашь свои.
Объявление функции
Функция начинается со слова fun, затем идут её имя и параметры в скобках. В Kotlin у каждого параметра обязательно указывается тип: name: String. После скобок через двоеточие пишут тип возвращаемого значения, а результат возвращают с помощью return. Функция, которая ничего не возвращает, имеет тип Unit, и его можно не писать.
fun greet(name: String, greeting: String = "Hello"): String {
return "$greeting, $name!"
}
fun printLine(length: Int = 10) {
println("-".repeat(length))
}
fun main() {
println(greet("Aysel"))
println(greet("Murad", "Salam"))
println(greet(greeting = "Hi", name = "Leyla"))
printLine()
printLine(5)
}Hello, Aysel! Salam, Murad! Hi, Leyla! ---------- -----
greeting: String = "Hello"— значение по умолчанию: если при вызове аргумент не передан, используется"Hello".greet(greeting = "Hi", name = "Leyla")— именованные аргументы: если указать имена параметров, порядок не важен, а код читается понятнее.printLineничего не возвращает — её типUnit, она просто выводит текст на экран.
Функции из одного выражения
Если вся работа функции — вычислить одно выражение, фигурные скобки и return можно убрать и записать выражение после знака =. Тип результата компилятор выведет сам. Поскольку if и when — выражения, их тоже можно использовать в такой функции.
fun square(x: Int) = x * x
fun isEven(n: Int) = n % 2 == 0
fun rectangleArea(width: Double, height: Double) = width * height
fun result(score: Int) = if (score >= 50) "passed" else "failed"
fun main() {
println(square(7))
println(isEven(10))
println(rectangleArea(4.0, 2.5))
println(result(73))
}49 true 10.0 passed
Функции-расширения
В Kotlin можно «добавить» новую функцию к существующему типу, даже к стандартному, например String или Int. Для этого перед именем функции пишут тип и точку: fun String.shout(). Внутри функции this — это само значение. Потом такую функцию вызывают как обычный метод: "salam".shout().
fun String.shout() = uppercase() + "!"
fun Int.isEven() = this % 2 == 0
fun Double.toManat() = "$this AZN"
fun main() {
println("salam".shout())
println(8.isEven())
println(12.5.toManat())
}SALAM! true 12.5 AZN
Лямбды
Лямбда — это короткая функция без имени, записанная в фигурных скобках: { x: Int -> x * 2 }. Слева от стрелки параметры, справа — тело; значение последнего выражения и есть результат лямбды. Лямбду можно сохранить в переменной, а её тип записывается так: (Int) -> Int — «принимает Int, возвращает Int». Если у лямбды один параметр, его можно не объявлять и обращаться к нему по имени it.
fun main() {
val double = { x: Int -> x * 2 }
val add: (Int, Int) -> Int = { a, b -> a + b }
val greet: (String) -> String = { "Hello, $it!" }
println(double(21))
println(add(3, 4))
println(greet("Elvin"))
}42 7 Hello, Elvin!
Функции высшего порядка
Функция, которая принимает другую функцию как параметр (или возвращает её), называется функцией высшего порядка. Ниже applyTwice применяет переданную ей операцию дважды. Если лямбда — последний аргумент, её можно вынести за скобки. А готовую функцию можно передать через ::, например ::multiply.
fun applyTwice(x: Int, f: (Int) -> Int): Int = f(f(x))
fun calculate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
return operation(a, b)
}
fun multiply(a: Int, b: Int) = a * b
fun main() {
println(applyTwice(3) { it + 10 })
println(applyTwice(5) { it * it })
println(calculate(8, 2) { a, b -> a - b })
println(calculate(8, 2, ::multiply))
}23 625 6 16
applyTwice(5) { it * it }: сначала 5 · 5 = 25, затем 25 · 25 = 625.Стандартная библиотека полна функций, принимающих лямбды. Даже repeat(3) { ... } из прошлого урока — функция высшего порядка! У строк count считает символы, подходящие под условие, а filter оставляет только их:
fun main() {
val word = "Programming"
println(word.count { it == 'm' })
println(word.filter { it !in "aeiou" })
println(word.any { it.isDigit() })
repeat(2) { i -> println("Attempt ${i + 1}") }
}2 Prgrmmng false Attempt 1 Attempt 2
repeat передаёт в лямбду номер шага, начиная с 0.Главное
- Функция записывается как
fun имя(параметр: Тип): ТипРезультата { ... }; функция без результата имеет типUnit. - Значения по умолчанию делают аргументы необязательными, а именованные аргументы снимают зависимость от порядка.
- Функция из одного выражения:
fun square(x: Int) = x * x. - Функция-расширение добавляет новый метод к существующему типу:
fun String.shout(). - Лямбда — функция без имени:
{ a, b -> a + b }; единственный параметр называетсяit. - Функция высшего порядка принимает другую функцию как параметр; последнюю лямбду можно вынести за скобки.
Проверь себя
Вопросов: 10. Каждый правильный ответ приносит XP.
fun area(w: Int, h: Int = 2) = w * h. Чему равно area(5)?