我正在阅读有关 Kotlin 的内容,但不太明白这个想法
据我了解,扩展函数赋予了具有新功能的类的能力,而无需从类继承
什么是接收者相同,除了它可以分配给变量
还有其他事吗?
有人可以举一些例子吗
与 Swift 和 C# 一样,Kotlin 提供了用新功能扩展类的能力,而无需修改类或从类继承。
您可能想知道为什么?因为我们无法对语言或SDK类进行编辑和添加功能。所以我们最终在 Java 中创建 Util 类。我相信所有项目都有一堆 *Utils 类来放置在代码库中多个位置使用的辅助方法。扩展函数有助于解决这个 Util 问题。
我们如何在 Java 中编写一个辅助方法来查找给定的 long 值是否指的是今天?
public class DateUtils {
public static boolean isToday(long when) {
// logic ...
}
}
我们通过传递 long 值作为参数来调用该方法:
void someFunc(long when) {
boolean isToday = DateUtils.isToday(when);
}
在 Kotlin 中,我们可以扩展 Long 类以在其中包含 isToday() 函数。我们可以像类中的任何其他成员函数一样对 Long 值本身调用 isToday() 函数。
// Extension function
fun Long.isToday(): Boolean {
// logic ...
}
fun someFunc(time: Long) {
val isToday = time.isToday()
}
与 Util 方法相比,Kotlin 使用扩展函数提供了更丰富的语法。
这提高了代码的可读性,进而提高了其可维护性。我们从 IDE 的代码补全中得到了一些帮助。因此我们不必记住使用哪个 Util 类来实现所需的功能。
在底层,Kotlin 编译器生成静态辅助方法,就好像我们将它们编写为 Java 静态 Util 方法一样。因此,我们在 Kotlin 中获得了这种漂亮且更丰富的语法,而无需牺牲任何性能。
与函数类似,Kotlin 也支持扩展属性,我们可以在现有类中添加属性。
高阶函数是以函数为参数,或者返回一个函数的函数。
让我们看看如何编写高阶函数。
fun execute(x: Int, y: Int, op: (Int, Int) -> Int): Int {
return op(x, y)
}
这里第三个参数( op )是一个函数,因此它使该函数成为一个高阶函数。参数op的类型是一个函数,以2个Int为参数并返回一个Int。
要调用这个高阶函数,我们可以传递一个函数或 lambda 表达式:
execute(5, 5) { a, b -> a + b }
以扩展函数作为参数的高阶函数称为 Lambda with Receiver。
让我们看一下 Kotlin 标准库中的 apply 函数的实现。
inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }
我们传递给这个apply函数的函数实际上是类型T的扩展函数。因此在lambda函数中,我们可以访问类型T的属性和函数,就像我们在类T本身中编写这个函数一样。
这里泛型类型 T 是接收者,我们传递一个 lambda 函数,因此名称为 Lambda with Receiver。
另一个例子:
inline fun SQLiteDatabase.inTransaction(func: SQLiteDatabase.() -> Unit) {
beginTransaction()
try {
func()
setTransactionSuccessful()
} finally {
endTransaction()
}
}
这里的inTransaction()是对SQLiteDatabase类的扩展函数,inTransaction()函数的参数也是对SQLiteDatabase类的扩展函数。这里 SQLiteDatabase 是作为参数传递的 lambda 的接收者。
调用该函数:
db.inTransaction {
delete( ... )
}
这里的delete()是
SQLiteDatabase
类的函数,并且由于我们传递的lambda是接收者的扩展函数SQLiteDatabase
我们可以访问delete函数而不需要任何额外的限定符,就像我们调用从 SQLiteDatabase
类本身内部调用函数。
虽然 @Bob 的回答关于 Kotlin 的信息比我希望的要丰富得多,包括扩展函数,但它并没有直接引用 https://kotlinlang.org/ 中描述的“函数文字与接收器”之间的比较docs/reference/lambdas.html#function-literals-with-receiver 和扩展函数 (https://kotlinlang.org/docs/reference/extensions.html)。 IE。之间的区别:
val isEven: Int.() -> Boolean = { this % 2 == 0 }
和
fun Int.isEven(): Boolean = this % 2 == 0
名称中的 receiver 部分是指这两种语法都将基本
Int
参数接收为 this
。
据我了解,两者之间的区别仅在于一个是确认函数类型的表达式,另一个是声明。从功能上来说,它们是等效的,都可以称为:
when { myNumber.isEven() -> doSomething(myNumber) }
但其中一个旨在用于扩展库,而另一个通常用作具有函数类型参数的函数的参数,特别是 Kotlin 构建器 DSL。