二十二)Kotlin简单易学 基础语法-定义扩展函数

定义扩展函数

扩展可以在不直接修改类定义的情况下增加类功能,扩展可以用于自定义类,也可用于比如List,String以及Kotlin标准库里的其他类。和继承相似,扩展也能共享类行为,在你无法接触某个类定义,或者某个类没有使用open修饰符,导致你无法继承它时,扩展就是增加类功能的最好选择。

String 扩展

//追加!!
fun String.ddExt(amount: Int = 1) = run { this + "!".repeat(amount) }

fun main() {
    //輸出abv!!
    println("abv".ddExt(3))
}

超类扩展

fun Any.easyPrint() = print((this))
"abv".easyPrint()

定义扩展函数

定义扩展函数和定义一般函数差不多,但有一点不一样,除了函数定义,你还需要指定接受功能扩展的接收者类型。

泛型扩展函数

新的泛型扩展函数不仅可以支持任何类型的接收者,还保留了接受者的类型信息,使用泛型类型后,扩展函数能够支持更多类型的接受者,使用范围更广了。

//追加!!
fun String.ddExt(amount: Int = 1) = run { this + "!".repeat(amount) }

fun <T> T.easyPrint(): T {
    println(this)
    return this
}

fun main() {
    "abc".easyPrint().ddExt(2)
}

扩展属性

除了给类添加功能扩展函数外,你还可以给类定义扩展属性,给String类添加一个扩展,这个扩展属性可以统计字符串有多少个元音字母。

val String.numVowels
    get() = count { "aeiou".contains(it) }

fun <T> T.easyPrint(): T {
    println(this)
    return this
}

fun main() {
    "abc".numVowels.easyPrint()
}

可空类扩展

你也可以扩展函数用于可空类型,在可空类型上定义扩展函数,你就可以直接在扩展函数体内解决可能出现的空值问题。

fun  String?.printWithDefault(default:String)= print(this ?:default)
fun main() {
    val nullableString:String?= null
    nullableString.printWithDefault("abc")
}

infix关键字

infix关键字适用于有单个参数的扩展和类函数,可以让你以更简洁的语法调用函数,如果一个函数定义使用了infix关键字,那么调用它时,接收者和函数之间的点操作以及参数的一对括号都可以不要。

infix fun  String?.printWithDefault(default:String)= print(this ?:default)
fun main() {
    val nullableString:String?= null
    //收者和函数之间的点操作以及参数的一对括号都可以不要
    nullableString printWithDefault "abc"
}

定义扩展文件

扩展函数需要在多个文件里面使用,可以将它定义在单独的文件,然后import。

fun <T> Iterable<T>.randomTake(): T = this.shuffled().first()


import randomTake

fun main() {
    val list = listOf("Jaso", "jack")
    list.randomTake()
}

重命名扩展

有时候,你想使用一个扩展或一个类,但它的名字不和你的意。

//有时候,你想使用一个扩展或一个类,但它的名字不和你的意。   as ramdomizer
import randomTake as ramdomizer

fun main() {
    val list = listOf("Jaso", "jack")
    list.ramdomizer()
}

Kotlin标准库中的扩展

Kotlin标准库的很多功能都是通过扩展函数和扩展属性来实现的,包含类扩展的标准库文件通常都是以类名加s后缀来命名的,例如Sequences.kt, Ranfes.kt,Maps.kt。

带接受者的函数字面量

apply函数是如何做到支持接收者对象的隐式调用的。

public inline fun<T> T.apply(block:T.()->Unit):T{block() return this}