【Kotlin】扩展属性、扩展函数

1 类的扩展

​ Kotlin 提供了扩展类或接口的操作,而无需通过类继承或使用装饰器等设计模式,来为某个类添加一些额外的属性或函数,我们只需要通过一个被称为扩展的特殊声明来完成。通过这种机制,我们可以将那些第三方类不具备的功能强行进行扩展,方便我们的操作。

1.1 扩展内置类

1.1.1 扩展属性

fun main() {     var str = "abc"     str.property = 5 // 打印: set property, value=5     var property = str.property // 打印: get property     println(property) // 打印: 10 }  var String.property: Int     set(value) {         println("set property, value=$value")     }     get() {         println("get property")         return 10     } 

​ 说明:扩展属性并不是真的往类中添加属性,也不会真的插入一个成员字段到类的定义中,导致没有变量存储我们的数据,我们只能明确定义一个 getter 和 setter 来创建扩展属性,才能让它使用起来真的像是类的属性一样。

​ 如下,如果没有定义 getter 和 setter方法,将会报错如下。

【Kotlin】扩展属性、扩展函数

1.1.2 扩展函数

fun main() {     var str = "abc"     str.myFun("xxx") // 打印: myFun, this=abc, value=xxx }  fun String.myFun(value: String) {     println("myFun, this=$this, value=$value") } 

1.2 扩展自定义类

1.2.1 扩展属性

1)扩展新属性

fun main() {     var stu = Student()     stu.name = "Mary" // 打印: set name, value=Mary     var name = stu.name // 打印: get name     println(name) // 打印: Tom }  class Student  var Student.name: String     set(value) {         println("set name, value=$value")     }     get() {         println("get name")         return "Tom"     } 

2)扩展旧属性

fun main() {     var stu = Student("Jack")     stu.name = "Mary" // 无打印     var name = stu.name // 无打印     println(name) // 打印: Mary }  class Student(var name: String)  var Student.name: String // 扩展属性不会生效     set(value) {         println("set name, value=$value")     }     get() {         println("get name")         return "Tom"     } 

​ 说明:如果扩展类中的同名同类型属性,扩展将不会生效。

1.2.2 扩展函数

1)扩展新函数

fun main() {     var stu = Student("Mary")     stu.test() // 打印: test, name=Mary }  class Student(var name: String)  fun Student.test() {     println("test, name=$name") } 

2)扩展旧函数

fun main() {     var stu = Student("Mary")     stu.test() // 打印: inner, name=Mary }  class Student(var name: String) {     fun test() {         println("inner, name=$name")     } }  fun Student.test() { // 扩展函数不会生效     println("extended, name=$name") } 

​ 说明:如果扩展类中的同名同参函数,扩展将不会生效。

1.3 重写父类的扩展函数

​ 类的扩展是静态的,实际上并不会修改它们原本的类,也不会将新成员插入到类中,仅仅是将我们定义的功能变得可调用,使用起来就像真的有一样。同时,在编译时也会明确具体调用的扩展函数。

1.3.1 扩展属性

fun main() {     var stu: Student = Student()     var name1 = stu.name // 打印: Student, get name     println(name1) // 打印: Mary     var peo: People = stu     var name2 = peo.name // 打印: People, get name     println(name2) // 打印: Tom }  open class People class Student: People()  var People.name: String     set(value) {         println("People, set name, value=$value")     }     get() {         println("People, get name")         return "Tom"     }  var Student.name: String     set(value) {         println("Student, set name, value=$value")     }     get() {         println("Student, get name")         return "Mary"     } 

1.3.2 扩展函数

fun main() {     var stu: Student = Student()     println(stu.type()) // 打印: Student     var peo: People = stu     println(peo.type()) // 打印: People }  open class People class Student: People()  fun People.type() = "People" fun Student.type() = "Student" 

1.4 匿名扩展函数

​ 匿名函数的使用详见 →【Kotlin】函数

fun main() {     var myFun: String.() -> Int = fun String.(): Int {         return this.length     }     println("abc".myFun()) // 打印: 3 } 

​ 可以使用 Lambda 表达式简化如下,Lambda 表达式的使用详见 → 【Kotlin】Lambda表达式

fun main() {     var myFun: String.() -> Int = {         this.length     }     println("abc".myFun()) // 打印: 3 } 

1.5 扩展函数作为参数

fun main() {     var len = "abc".len { this.length }     println(len) // 打印: 3 }  fun String.len(func: String.() -> Int): Int {     return func() } 

2 官方扩展函数

2.1 源码

​ Kotlin 提供了一些泛型扩展函数(在 Standard.kt 中),如:apply、also、run、let、takeIf、takeUnless 等。

​ apply、also、run、let 的区别如下,作用是执行 block 函数的内容,并且返回 T 或 block 的返回值,通常用于判空处理。

函数 block是否为扩展函数 block入参 block返回值 函数返回值 访问 T 对象
apply T this
also T T it
run R R this
let T R R it

2.1.1 apply

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

2.1.2 also

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

2.1.3 run

public inline fun <T, R> T.run(block: T.() -> R): R {     ...     return block() } 

2.1.4 let

public inline fun <T, R> T.let(block: (T) -> R): R {     ...     return block(this) } 

2.1.5 takeIf

public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? {     ...     return if (predicate(this)) this else null } 

2.1.6 takeUnless

public inline fun <T> T.takeUnless(predicate: (T) -> Boolean): T? {     ...     return if (!predicate(this)) this else null } 

2.1.7 with

public inline fun <T, R> with(receiver: T, block: T.() -> R): R {     ...     return receiver.block() } 

​ 说明:with 不是扩展函数,但入参 block 是扩展函数。

2.1.8 to

public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that) 

2.1.9 toList

public fun <T> Pair<T, T>.toList(): List<T> = listOf(first, second) public fun <T> Triple<T, T, T>.toList(): List<T> = listOf(first, second, third) 

2.2 应用

2.2.1 apply 应用

fun main() {     var stu = Student()     test(stu) }  fun test(stu: Student?) {     stu?.apply {         this.name = "Tom"         this.age = 23     }     println(stu) // 打印: [Tom, 23] }  class Student {     var name: String? = null     var age: Int = 0      override fun toString(): String {         return "[$name, $age]"     } } 

​ 说明:also、run、let 的应用与 apply 类似。

2.2.2 takeIf 应用

fun main() {     var str = "ABC"     var str2 = str.takeIf { it.length % 2 == 1 }?.let { it + it.reversed().substring(1) }     println(str2) // 打印: ABCBA } 

2.2.3 with 应用

fun main() {     var str = "ABC"     var len = with(str) { this.length }     println(len) // 打印: 3 } 

​ 声明:本文转自【Kotlin】扩展属性、扩展函数

发表评论

评论已关闭。

相关文章