- 定义扩展函数
- 泛型扩展函数
- 扩展属性
- 可空类扩展
- infix
- 定义扩展文件
- 重命名扩展
- Kotlin标准库中的扩展
- 带接收者的函数字面量
1.定义扩展函数
扩展可以在不直接修改类定义的情况下增加类功能,扩展可以用于自定义类
也可以用于标准库里的其他类。
和继承相似,扩展也能共享类的行为
在无法接触某个类的定义或者某个类没有使用open导致无法继承时,扩展就是选择
// 给String添加扩展函数
fun String.addExt (amount : Int = 1) : String{
return this + "!".repeat(amount)
}
fun Any.easyPrintln() = println(this)
fun main() {
println("abc".addExt(4))
}
需要指定接收功能扩展的接收者类型
2.泛型扩展函数
新的泛型扩展函数不仅可以支持任何类型的接收者,还保留了接收者的信息
使用泛型类型后,扩展函数能够支持更多类型的接收者
// 给String添加扩展函数
fun String.addExt (amount : Int = 1) : String{
return this + "!".repeat(amount)
}
fun <T> T.easyPrintln() : T {
println(this)
return this
}
fun main() {
"abc".easyPrintln().addExt().easyPrintln()
}
3.扩展属性
除了给类添加功能扩展函数外,还可以给类定义扩展属性
// 给String添加属性
val String.numVowels
get() = count { "aeiou".contains(it) }
fun <T> T.easyPrintln() : T {
println(this)
return this
}
fun main() {
"The people's republic of China".numVowels.easyPrintln()
}
4.可空类扩展
在可空类型上定义扩展函数就可以直接在扩展函数体内解决可能出现的null值问题
// 给String添加可空扩展函数
fun String?.printWithDefault(default : String = "jyl") = print(this ?: default)
fun main() {
val nullableString : String? = null
nullableString.printWithDefault()
}
5.infix
infix关键字适用于有单个参数的扩展和类函数,可以更简洁的语法调用函数
使用了infix后,接收者和函数之间的点操作以及参数的一对括号都可以不要
infix不允许参数设定默认值
// 给String添加可空扩展函数
infix fun String?.printWithDefault(default : String ) = print(this ?: default)
fun main() {
val nullableString : String? = null
nullableString.printWithDefault("abc")
nullableString printWithDefault "abc"
}
6.定义扩展文件
扩展函数需要在多个文件里使用,可以定义在单独的文件,然后import
//集合
fun <T> Iterable<T>.randomTake() : T = this.shuffled().first()
import com.jason.kotlin.extension.randomTake
fun main() {
val list = listOf("Jason","Jack","Tom")
val set = setOf("Jason","Jack","Tom")
println(list.randomTake())
println(set.randomTake())
}
7.重命名扩展
可以用as关键字修改导入的类或函数名
import com.jason.kotlin.extension.randomTake as randomizer
fun main() {
val list = listOf("Jason","Jack","Tom")
val set = setOf("Jason","Jack","Tom")
println(list.randomizer())
println(set.randomizer())
}
8.Kotlin标准库中的扩展
Kotlin标准库提供的很多功能都是通过扩展函数和扩展属性来实现的
包含类扩展的标准库文件通常是以类名加s来命名,如Maps、Ranges
9.带接收者的函数字面量
可支持接收者对象的隐式调用
// () -> Unit
// T.() -> Unit 传一个泛型的扩展函数
//为什么要传入扩展函数,而不是普通的匿名函数
//扩展函数里自带了this的隐式调用
fun String.addExt () = "!".repeat(this.count())
//为什么是泛型的扩展函数 -> 多态
//只支持File对象
//public inline fun File.apply(block: File.() -> Unit): File {
// block()
// return this
//}
public inline fun <T> T.apply(block: T.() -> Unit): T {
block()
return this
}
fun main() {
File("xxx").apply {
// this.setReadable(true)
setReadable(true)
}
//1.定义扩展函数
fun File.ext() : Unit{
setReadable(true)
}
//2.给block变量赋值
val block = File::ext
//3.传入apply函数
File("xx").apply{
block
}
}