扩展函数
假设你发现了一个几乎能满足你所有需求的库,但如果它再多提供一个或两个额外的成员函数,就能完美解决你的问题。
但这并不是你的代码,要么你无法访问源代码,要么你无法控制它。每当新版本发布时,你都必须重复进行修改。
Kotlin 的扩展函数可以有效地向现有类添加成员函数。你所扩展的类型被称为 接收者。要定义一个扩展函数,你需要在函数名之前加上接收者类型:
fun ReceiverType.extensionFunction() { ... }
这将为String
类添加两个扩展函数:
// ExtensionFunctions/Quoting.kt
package extensionfunctions
import atomictest.eq
fun String.singleQuote() = "'$this'"
fun String.doubleQuote() = "\"$this\""
fun main() {
"Hi".singleQuote() eq "'Hi'"
"Hi".doubleQuote() eq "\"Hi\""
}
您可以像调用类成员一样调用扩展函数。
要使用来自另一个包的扩展函数,您必须先导入它们:
// ExtensionFunctions/Quote.kt
package other
import atomictest.eq
import extensionfunctions.doubleQuote
import extensionfunctions.singleQuote
fun main() {
"Single".singleQuote() eq "'Single'"
"Double".doubleQuote() eq "\"Double\""
}
您可以使用关键字 this
访问成员函数或其他扩展函数。与类内部一样,您也可以省略 this
关键字,因此无需显式限定:
// ExtensionFunctions/StrangeQuote.kt
package extensionfunctions
import atomictest.eq
// Apply two sets of single quotes:
fun String.strangeQuote() =
this.singleQuote().singleQuote() // [1]
fun String.tooManyQuotes() =
doubleQuote().doubleQuote() // [2]
fun main() {
"Hi".strangeQuote() eq "''Hi''"
"Hi".tooManyQuotes() eq "\"\"Hi\"\""
}
- [1]
this
指的是String
接收器。 - [2] 我们省略了第一个
doubleQuote()
函数调用的接收器对象(this
)。
创建自己类的扩展有时可以产生更简洁的代码:
// ExtensionFunctions/BookExtensions.kt
package extensionfunctions
import atomictest.eq
class Book(val title: String)
fun Book.categorize(category: String) =
"""title: "$title", category: $category"""
fun main() {
Book("Dracula").categorize("Vampire") eq
"""title: "Dracula", category: Vampire"""
}
在 categorize()
内部,我们可以直接访问 title
属性,无需显式限定。
请注意,扩展函数只能访问被扩展类型的
public
元素。因此,扩展函数只能执行与普通函数相同的操作。您可以将Book.categorize(String)
重写为categorize(Book, String)
。使用扩展函数的唯一原因是语法,但这种语法糖非常强大。对于调用代码而言,扩展函数看起来与成员函数相同,而且IDE在列出对象可调用的函数时会显示扩展函数。
练习和解答可以在 www.AtomicKotlin.com 找到。