Kotlin标准函数、扩展函数、运算符重载、高阶函数、内联函数及lanmbda表达式

一、标准函数:

csharp 复制代码
Kotlin的标准函数指的是Standard.kt 文件中定义的函数,可以自由调用所有标准函数。
Kotlin标准库中有一些函数,这些函数目的就是在对象上下文中执行代码块。当对一个对象调用这样的函数并提供一个Lambda表达式时,它会形成一个临时作用域,在此作用域中,可以访问该对象[成员和方法]而无需其名称,这些函数称为作用域函数。共有let、run、with、apply以及also五种作用域函数。

obj.let{(T) -> R}扩展函数:

kotlin 复制代码
val study = PersonInfo("三只牛", 28, 1)
study.let {
    LogUtils.d("name:${it.name}, year:${it.year}")
}
kotlin 复制代码
/**
 * Calls the specified function [block] with `this` value as its argument and returns its result.
 *
 * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#let).
 */
@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block(this)
}

with(obj){}扩展函数:

perl 复制代码
with(study){
    "name: ${name} year:${year} sex:${sex}"
}
kotlin 复制代码
/**
 * Calls the specified function [block] with the given [receiver] as its receiver and returns its result.
 *
 * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#with).
 */
@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return receiver.block()
}

obj.run{}扩展函数

arduino 复制代码
study.run {
    "hello, ${name}"
}
kotlin 复制代码
/**
 * Calls the specified function [block] with `this` value as its receiver and returns its result.
 *
 * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#run).
 */
@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}

obj.apply{ -> T}扩展函数, 返回obj自己

ini 复制代码
study.apply {
    name = "李铁"
}
kotlin 复制代码
/**
 * Calls the specified function [block] with `this` value as its receiver and returns `this` value.
 *
 * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#apply).
 */
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    return this
}

obj.aslo{(T) -> T} 返回obj自己

bash 复制代码
study.also {
    LogUtils.d("name:${it.name}, ${it.year}")
}
kotlin 复制代码
/**
 * Calls the specified function [block] with `this` value as its argument and returns `this` value.
 *
 * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#also).
 */
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.also(block: (T) -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block(this)
    return this
}
  1. obj.takeIf、obj.take Unless扩展函数: 如果符合条件,则返回T,否则返回null。当以提供的谓词在对象上进行调用时,若该对象与谓词匹配,则 takeIf 返回此对象。否则返回 null。因此,takeIf 是单个对象的过滤函数。反之,takeUnless如果不匹配谓词,则返回对象,如果匹配则返回 null。该对象作为 lambda 表达式参数(it)来访问。
ini 复制代码
val random = Random.nextInt(100)
val even = random.takeIf { it % 2 == 0 }
val odd = random.takeUnless { it % 2 == 0 }

下面是函数原型

kotlin 复制代码
/**
 * Returns `this` value if it satisfies the given [predicate] or `null`, if it doesn't.
 *
 * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#takeif-and-takeunless).
 */
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? {
    contract {
        callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
    }
    return if (predicate(this)) this else null
}
kotlin 复制代码
/**
 * Returns `this` value if it _does not_ satisfy the given [predicate] or `null`, if it does.
 *
 * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#takeif-and-takeunless).
 */
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.takeUnless(predicate: (T) -> Boolean): T? {
    contract {
        callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
    }
    return if (!predicate(this)) this else null
}

二、扩展函数:

  1. Kotlin的扩展函数是一种特殊的函数,允许在不修改原始类定义的情况下向现有类添加新的函数。扩展函数可以像普通函数一样使用,并且可以在任何地方调用。定义一个扩展函数,可以使用以下语法:
kotlin 复制代码
    fun class.funName(params):returnType

三、运算符重载:

kotlin 复制代码
同一运算符在不同的环境所表现的效果不同,如"+"在两个Int值之间表示两者的数值相加,在两个字符串之间表示,将字符串拼接,同时kotlin允许我们将任意两个类型的对象进行"+"运算,或者其他运算符操作。
kotlin 复制代码
class A {
    operator fun plus(a: A): A {
        //相关逻辑
    }
}

表达式 函数名

a * b a.times(b)

a / b a.div(b)

a % b a.rem(b)

a + b a.plus(b)

a - b a.minus(b)

a++ a.inc()

a-- a.dec()

!a a.not()

a == b a.equals(b)

"a > b"、"a < b"、"a >= b"、"a >= b" a.compareTo(b)

a..b a.rangeTo(b)

a[b] a.get(b)

a[b] = c a.set(b, c)

a in b b.contains(a)

四、高阶函数:

xml 复制代码
参数是函数类型或返回值是函数类型的函数。<br>

函数类型定义:(String, Int) -> Unit

kotlin 复制代码
fun hightFun(num1: Int, num2: Int, operation: (Int, Int) -> Int): Int {
    val result = operation(num1, num2)
    return result
}

引用函数类型有几种方式: 1、双冒号。 在 Kotlin 里,一个函数名的左边加上双冒号,它就不表示这个函数本身了,而表示一个对象,或者说一个指向对象的引用,但这个对象可不是函数本身,而是一个和这个函数具有相同功能的对象。下面的例子表示将plus()函数作为参数传递给hithFun()函数。

kotlin 复制代码
fun plus(num1: Int, num2: Int) : Int {
    return num1 + num2
}
val result = hightFun(10, 8, ::plus)

2、匿名函数。

kotlin 复制代码
val result = hightFun(10, 8, fun(num1: Int, num2: Int) = num1 + num2)

3、lambda表达式。

ini 复制代码
val result = hightFun(10, 8) {
    n1, n2 -> n1 + n2
} 

Kotlin高阶函数的实现原理是将Lambda表达式在底层转为如上第二种匿名类的实现方式。每调用一次Lambda都会创建一个新的匿名类实例,会造成额外的内存和性能开销。为此Kotlin提供了内联函数功能。

五、内联函数:

Kotlin编译器会将内联函数中的代码在编译时自动替换到调用它的地方,这样就不存在运行时的开销了。一般会把高阶函数声明为内联函数,即在定义高阶函数时加上inline关键字声明,这是一种良好的编程习惯,绝大多数高阶函数是可以直接声明成内联函数的。

kotlin 复制代码
inline fun hightFun(num1: Int, num2: Int, operation: (Int, Int) -> Int): Int {
    val result = operation(num1, num2)
    return result
}

如果一个内联高阶函数中含有多个函数类型参数,其中有一个函数类型参数不想内联,可在该参数前加上noinline关键字。

kotlin 复制代码
inline fun inlineFun(block1:() -> Unit, noinline block2: () -> Unit) {

}

为什么Kotlin还提供noline来排除内联功能? 因为内联的函数类型参数在编译的时候会被代码替换,因此它没有真正的参数属性。非内联的函数类型参数可以自由地传递给其他函数,因为它就是一个真实的参数,而内联的参数类型只允许传递给另外一个内联函数,这是它最大的局限性。 内联函数和非内联函数另一个区别是内联函数所引用的Lambda表达式中可以使用return关键字进行函数返回,而非内联函数只能局部返回。(在Java8语言中,lambda表达式是可以明确使用return关键字的,而Kotlin语言中,lambda表达式却不能使用return关键字。而上面内联函数所引用的Lambda表达式中可以使用return关键字进行的函数返回是表示退出该lambda函数逻辑,局部返回,不再执行Lambda表示式的剩余内容。)

如果在内联高阶函数中创建了另外的Lambda或匿名类的实现,并且在这些实现中调用函数的参数,就会提示错误。如

kotlin 复制代码
inline fun runRunnable(block: () -> Unit) {
    val runnable = Runnable {
        block() // 提示错误
    }
}

因为内联函数所引用的Lambda表达式允许使用return进行函数返回,而高阶函数的匿名类实现中不允许使用return造成了冲突。为什么高阶函数的匿名类实现中不允许使用return?匿名类中调用的函数类型参数是不可能进行外层调用函数返回的(匿名类啊,你连名字都没有你怎么在外部调用?),最多只能对匿名类中的函数调用进行返回。所以高阶函数的匿名类实现中不允许使用return。

crossinline用于保证内联函数Lambda表达式中一定不会使用return进行函数返回。

kotlin 复制代码
inline fun runRunnable(crossinline block: () -> Unit) {
    val runnable = Runnable {
        block() 
    }
}

声明后runRunnable函数的Lambda中无法使用return进行函数返回了,仍然可以使用return@runRunnable进行局部返回

reified 关键字 reified 配合 inline可以将泛型实例化

kotlin 复制代码
inline fun <reified T> startActivity(context: Context, block: Intent.() -> Unit) {
    val intent = Intent(context, T::class.java)
    intent.block()
    context.startActivity(intent)
 }
相关推荐
sun0077006 小时前
android ndk编译valgrind
android
AI视觉网奇7 小时前
android studio 断点无效
android·ide·android studio
jiaxi的天空7 小时前
android studio gradle 访问不了
android·ide·android studio
No Silver Bullet8 小时前
android组包时会把从maven私服获取的包下载到本地吗
android
catchadmin8 小时前
PHP serialize 序列化完全指南
android·开发语言·php
tangweiguo0305198710 小时前
Kable使用指南:Android BLE开发的现代化解决方案
android·kotlin
00后程序员张12 小时前
iOS App 混淆与资源保护:iOS配置文件加密、ipa文件安全、代码与多媒体资源防护全流程指南
android·安全·ios·小程序·uni-app·cocoa·iphone
柳岸风14 小时前
Android Studio Meerkat | 2024.3.1 Gradle Tasks不展示
android·ide·android studio
编程乐学14 小时前
安卓原创--基于 Android 开发的菜单管理系统
android
whatever who cares16 小时前
android中ViewModel 和 onSaveInstanceState 的最佳使用方法
android