美文网首页
Kotlin函数扩展和属性扩展

Kotlin函数扩展和属性扩展

作者: 因为我的心 | 来源:发表于2022-11-25 14:26 被阅读0次

    一、前言:

    我们都知道java要扩展一个已有类的方法和属性必须采用继承、组合或直接修改现有类来进行功能和属性的扩展。而kotlin是完全支持扩展方法和扩展属性的,这样我们就可以像正常调用对象方法一样使用扩展方法和属性了。

    二、扩展方法

    1、扩展方法的定义语法如下:

    fun [扩展类].(参数列表){
        //方法执行体
    }
    

    示例:

       override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            //创建对象
            val apple = Apple()
            apple.test()
            //使用的时候和调用普通方法没有任何区别
            apple.info()
        }
    
    
        //1、Apple类
        class Apple{
            fun test(){
                Log.d("LUO","test")
            }
        }
        //2、给Apple扩展了一个info方法
        fun Apple.info(){
            Log.d("LUO","info")
        }
    

    2、kotlin也是支持泛型类的扩展的,比如我们为List添加一个交换两个元素位置的方法代码如下:

    fun MutableList<Int>.swap(index1: Int, index2: Int) {
        val tmp = this[index1] // “this”对应该列表
        this[index1] = this[index2]
        this[index2] = tmp
    }
    //使用
    fun main(args:Array<String>) {
        val list = mutableListOf(1, 2, 3)
        list.swap(0,1)
        Log.d("LUO","list = $list")
    }
    

    3、扩展的实现机制

    kotlin的扩展其实是没有修改原来的类的。kotlin扩展的本质其实就是定义了一个函数,当程序用对象调用扩展方法时,kotlin在编译时会执行静态解析(就是根据调用对象、方法名来找到扩展函数,转换为函数调用)。
    kotlin在编译时会经过一下几步:

    • 检查调用对象的类型
    • 检查对象所属的类是否定义了该方法,如果类本身定义了该方法,kotlin不需要任何处理直接执行。
    • 如果类本身不包含这个方法,kotlin会检查程序中是不是有这个类的对应扩展方法,如果有,kotlin会执行静态解析,会将调用处的方法替换为这个扩展函数。
    • 如果类不包含对应的方法也在程序中没有找到相应的扩展函数,编译器将会报错。
    • 在kotlin中成员方法执行动态解析(调用哪个方法由运行时类型决定),扩展方法执行静态解析(调用哪个方法由编译时类型决定)。

    三、扩展属性

    扩展属性有以下原则:

    • 扩展属性不能有初始值(没有存储属性值的幕后宇段)
    • 不能用 field 关键字显式访问幕后字段。
    • 扩展只读属性必须提供 getter 方法, 扩展读写属性必须提供 getter、setter 方法。

    1、顶级的方法去定义扩展方法(属性)

    示例代码:

     override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            var user = User("赵","薇薇")
            var name =  user.fullName
            Log.d("LUO","---name:$name")
            user.fullName = "我是.小明"
            Log.d("LUO","---name:${user.fullName}")
        }
    
        //1、User对象
        class User(var firstName: String, var lastName: String) {}
        
        //2、为 User的fullName 扩展读写属性
        var User.fullName: String
            get() = "${firstName}.${lastName}"
            set(value) {
                Log.d("LUO","执行扩展属性 fullName setter 方法")
                //value 字符串中不包含.或包含几个 都不行
                if ("." !in value || value.indexOf(".") != value.lastIndexOf(".")) {
                    Log.d("LUO","您输入的 fullName 不合法")
                } else {
                    var tokens = value.split("·")
                    firstName = tokens[0]
                    lastName = tokens[1]
                }
            }
    

    2、以成员的方式扩展方法

    kotlin也支持以成员的方法定义扩展和属性。
    对于成员的方式定义的扩展,

    • 一方面属于被扩展的类,因此可以访问被扩展类的方法(属性);
    • 另一方面它还可以在扩展方法(属性)中调用它所在类的成员。

    示例代码如下:

    class A {
        fun bar() = println("A类的bar方法")
    }
    
    class B {
        fun baz() = println("B类的baz方法")
        fun A.foo() {
            this.bar()//this指的是被扩展类。
            this@B.baz()//this可以省略
        }
    
        fun test(target: A) {
            target.bar()//调用目标类的成员方法
            target.foo()//调用目标类的扩展方法
        }
    }
    //测试程序
    fun main(args: Array<String>) {
        var b = B()
        b.test(A())
    }
    

    输出结果:

    A类的bar方法
    A类的bar方法
    B类的baz方法
    

    注意:如果扩展类和扩展方法所在类中的方法签名一致,那么如果不加this@类名指定调用哪个类的方法时,默认调用的是被扩展类的同名方法。

    四、什么情况用扩展

    • 想要动态的为已有的类添加方法或属性时。
    • 需要用更好的方式组织一些工具方法时。

    参考:https://blog.csdn.net/guojingbu/article/details/121196705

    相关文章

      网友评论

          本文标题:Kotlin函数扩展和属性扩展

          本文链接:https://www.haomeiwen.com/subject/ylcxfdtx.html