一、标准函数:
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
}
- 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
}
二、扩展函数:
- 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)
}