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)
 }
相关推荐
dal118网工任子仪5 小时前
91,【7】 攻防世界 web fileclude
android·前端
taopi20245 小时前
android java 用系统弹窗的方式实现模拟点击动画特效
android
fanged5 小时前
Android学习19 -- 手搓App
android
dal118网工任子仪5 小时前
99,[7] buuctf web [羊城杯2020]easyphp
android·前端·android studio
村口老王10 小时前
鸿蒙开发——应用程序包及模块化设计
android·前端·harmonyos
6v6博客10 小时前
如何在 Typecho 中实现 Joe 编辑器标签自动填充
android·编辑器
程序员牛肉14 小时前
为什么网络上一些表情包在反复传播之后会变绿?“电子包浆”到底是怎么形成的?
android
志尊宝14 小时前
Android 深入探究 JSONObject 与 JSONArray:Android 中的数据解析与数组操作全解析
android
莫名有雪1 天前
BUUCTF_[网鼎杯 2020 朱雀组]phpweb(反序列化绕过命令)
android
爱写代码的山山1 天前
虚幻UE5手机安卓Android Studio开发设置2025
android·ue5·虚幻