扩展函数
- 扩展可以在不直接修改类定义的情况下增加类功能
- 扩展可以用于自定义类,也可以用于标准函数
- 和继承相似,扩展也能共享类行为,在无法接触某个类定义,或者某个类没有使用open修饰符,导致无法继承它时,扩展就是增加类功能的最好选择
- 和定义一般函数差不多,但需要指定接收功能扩展的接受者类型
- 默认是public,整个工程有效,若需要只在当前文件有效,可以定义为private
- 扩展函数里自带了接收者对象的this隐式调用
//给字符串追加若干个感叹号
fun String.addExt(amount:Int = 1) = this "!".repeat(amount)
//在超类上定义扩展函数,Any的所有子类都能使用该函数
fun Any.easyPrint() = println(this)
class TeBot()
fun main() {
println("abc".addExt(2))
"abc".easyPrint()
val teBot = TeBot()
teBot.easyPrint()
}
泛型扩展函数
新的泛型扩展函数不仅可以支持任何类型的接受者,还保留了接收者的类型信息
代码语言:javascript复制//泛型扩展函数
fun <T> T.easyPrint2():T{
println(this)
return this
}
fun main() {
println("abc".addExt(2))
"abc".easyPrint2().addExt(2).easyPrint2()
}
可空类扩展
- 在可空类上定义扩展函数,可以直接在扩展函数体内解决可能出现的空值问题
- infix关键字适用于有单个参数的扩展和类函数。如果一个函数定义使用了infix关键字,那么调用它时,接收者和函数之间的点操作以及参数的一对括号都可以不要
//可空类型扩展函数
//fun String?.printWIthDefault(default:String) = print(this ?: default)
infix fun String?.printWIthDefault(default:String) = print(this ?: default)
fun main() {
val nullableString: String? = "efg"
// nullableString.printWIthDefault("abc")
//加了infix关键字
nullableString printWIthDefault "abc"
}
扩展属性
代码语言:javascript复制//增加统计元音字母属性
val String.numVowels
get() = count{
"aeiou".contains(it)
}
fun main() {
"the people's republic of china".numVowels.easyPrint()
}
扩展文件和重命名扩展
代码语言:javascript复制package extention
//扩展文件
fun <T> Iterable<T>.randomTake(): T = this.shuffled().first()
import extention.randomTake
//重命名扩展
import extention.randomTake as random
//扩展文件
fun main() {
val list = listOf("Jak", "Jim")
val set = setOf("Jak", "Jim")
list.randomTake()
list.random()
}
apply函数详解
代码语言:javascript复制import java.io.File
//apply函数中的扩展函数
//从T.apply可以看出apply本身是一个扩展函数,并且是泛型扩展函数 返回类型是泛型T
//入参block是一个匿名函数() -> Unit,
// T.() -> Unit表示的是一个扩展函数,在T上扩展了一个匿名函数,
// 之所以要传扩展函数是因为扩展函数内部包括隐式调用,有this
//匿名函数也可以是扩展函数,下面的匿名函数的内部this指向一个File对象
//File.() -> Unit
public inline fun <T> T.apply(block: T.() -> Unit): T {
block()
return this
}
fun main() {
File("xxx").apply {
setWritable(true)
setReadable(true)
}
//分解一下
//1.定义扩展函数
fun File.ext() : Unit {
setReadable(true)
}
//2.给block赋值
val block = File::ext
//3.传入apply函数
File("xxx").apply(block)
}