• 【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方法,将会报错如下。

    img

    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.apply(block: T.() -> Unit): T {
        ...
        block()
        return this
    }
    

    2.1.2 also

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

    2.1.3 run

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

    2.1.4 let

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

    2.1.5 takeIf

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

    2.1.6 takeUnless

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

    2.1.7 with

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

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

    2.1.8 to

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

    2.1.9 toList

    public fun  Pair.toList(): List = listOf(first, second)
    public fun  Triple.toList(): List = 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】扩展属性、扩展函数

  • 相关阅读:
    深度学习自学笔记三:向量化逻辑回归和Python中的广播
    Linux权限总结
    M2 MacbookPro配置Spark源码运行环境
    arthas实用梳理篇
    学生花卉网网页设计作品 学生鲜花网页模板 简单在线花店主页成品 鲜花网页制作 HTML学生花店商城网站作业设计
    在Kubernetes上部署Spring Boot微服务实践
    体育竞技分析
    200PPI转以太网与易控modbusTCP客户端通信配置
    5、从RCNN到FasterRCNN(各模块独立训练到端到端检测框架)
    史上最难618,TCL夺得电视行业京东和天猫份额双第一
  • 原文地址:https://www.cnblogs.com/zhyan8/p/18115112