Demystifying Advanced Kotlin Concepts Pt.1 - статья о не совсем очевидных возможностях Kotlin и способах их применения. Краткое содержание:
1. Вложенные функции. Kotlin позволяет объявить функцию внутри функции. Причем вложенная функция будет иметь доступ к переменным внешней. Эту возможность можно использовать для создания переиспользуемых блоков кода, не захламляя пространство имен класса.
fun OuterFunction(param:Int) {
val outerVar = 11
fun localFunction(){
println(params)
println(outerVar)
}
}
2. Инфиксные функции:
infix fun String.extensionFunction(x: Int): Int {
...
}
val str = "hello"
str extensionFunction 2
3. Анонимные функции. Это почти то же, что и лямбда, но с возможностью возвращать различные значения:
fun op(x:Int, op:(Int) -> Int): Int {
return op(x)
}
// лямбда
op(3, {it * it})
// анонимная функция
op(3, fun(x): Int {
if(x > 10) return 0
else return x * x
})
4. Инлайнинг функций. При использовании функций высшего порядка (тех, что могут принимать другую функцию как аргумент), Kotlin генерирует анонимный класс для каждой переданной функции-аргумента. Это приводит к оверхеду, которого можно избежать если объявлять функции высшего порядка с ключевым словом inline. В этом случае вместо реального вызова функции, компилятор просто вставит ее код в место вызова.
inline fun op(op: () -> Unit){
println("This is before lambda")
op()
println("this is after lambda")
}
fun main(args: Array) {
op({println("this is the actual function")})
}
5. Возврат из лямбды. Ключевое слово return, будучи использованным внутри лямды, вернет управление не из самой лямбды, а из внешней функции. Чтобы этого избежать следует использовать метки:
fun ContainingFunction() {
val nums = 1..100
numbers.forEach {
if(it % 5 == 0) {
return@ForEach
}
}
println("Hello!")
}
6. Лямбды-расширения. В Kotlin есть концепция функций-расширений: к любому классу в любой момент времени можно добавить метод, который будет иметь доступ к пространству имен класса. Такими функциями-раширениями также могут быть лямбды. Это позволяет создавать DSL, о которых мы уже говорили выше. Пример.
// лямбда
f:() -> Unit
// лямбда-расширение
f:SomeFunctionOrClass.() -> Unit
7. Вызов инстансов класса. Kotlin позволяет вызывать объект класса как функцию. Все, что нужно - добавить в код класса метод invoke().
class Manager {
operator fun invoke(value:String) {
prinln(value)
}
}
...
val manager = Manager()
...
manager("Hello, world!")
#кодинг
1. Вложенные функции. Kotlin позволяет объявить функцию внутри функции. Причем вложенная функция будет иметь доступ к переменным внешней. Эту возможность можно использовать для создания переиспользуемых блоков кода, не захламляя пространство имен класса.
fun OuterFunction(param:Int) {
val outerVar = 11
fun localFunction(){
println(params)
println(outerVar)
}
}
2. Инфиксные функции:
infix fun String.extensionFunction(x: Int): Int {
...
}
val str = "hello"
str extensionFunction 2
3. Анонимные функции. Это почти то же, что и лямбда, но с возможностью возвращать различные значения:
fun op(x:Int, op:(Int) -> Int): Int {
return op(x)
}
// лямбда
op(3, {it * it})
// анонимная функция
op(3, fun(x): Int {
if(x > 10) return 0
else return x * x
})
4. Инлайнинг функций. При использовании функций высшего порядка (тех, что могут принимать другую функцию как аргумент), Kotlin генерирует анонимный класс для каждой переданной функции-аргумента. Это приводит к оверхеду, которого можно избежать если объявлять функции высшего порядка с ключевым словом inline. В этом случае вместо реального вызова функции, компилятор просто вставит ее код в место вызова.
inline fun op(op: () -> Unit){
println("This is before lambda")
op()
println("this is after lambda")
}
fun main(args: Array) {
op({println("this is the actual function")})
}
5. Возврат из лямбды. Ключевое слово return, будучи использованным внутри лямды, вернет управление не из самой лямбды, а из внешней функции. Чтобы этого избежать следует использовать метки:
fun ContainingFunction() {
val nums = 1..100
numbers.forEach {
if(it % 5 == 0) {
return@ForEach
}
}
println("Hello!")
}
6. Лямбды-расширения. В Kotlin есть концепция функций-расширений: к любому классу в любой момент времени можно добавить метод, который будет иметь доступ к пространству имен класса. Такими функциями-раширениями также могут быть лямбды. Это позволяет создавать DSL, о которых мы уже говорили выше. Пример.
// лямбда
f:() -> Unit
// лямбда-расширение
f:SomeFunctionOrClass.() -> Unit
7. Вызов инстансов класса. Kotlin позволяет вызывать объект класса как функцию. Все, что нужно - добавить в код класса метод invoke().
class Manager {
operator fun invoke(value:String) {
prinln(value)
}
}
...
val manager = Manager()
...
manager("Hello, world!")
#кодинг