解析Kotlin伴随对象

最近开始学习Kotlin,看好kotlin,有不少语法糖啊,先在android平台站稳脚跟,然后慢慢向其他平台延伸

引言

最近在学Kotlin,在学习的过程中,越来越强烈的感觉到,要想掌握Kotlin的精髓,必须利用的Java的语言特性来加深理解,对于学习Kotlin的很多语法糖特性大有裨益!

这篇文章的重点有:

  • 伴随对象的简单栗子
  • 编译class文件,理解伴随对象的实现,与函数/属性扩展的区别

引用官方描述:

Kotlin, similar to C# and Gosu, provides the ability to extend a class with new functionality without having to inherit from the class or use any type of design pattern such as Decorator. This is done via special declarations called extensions. Kotlin supports extension functions and extension properties.

Simply就是Kotlin无需通过继承或装饰器模式,即可为特定类拓展出新的函数和属性,然后就可以直接使用了

1.举一个简单栗子:

fun main(args: Array<String>) {
    Extension.action()
    println(Extension.data)
}

class Extension {

    var variety: String = "origin "

    companion object {
        fun action() {
            println("action")
        }

        val data = "123"
    }

}

伴随对象的一般定义如上,在目标Extension类中定义伴随对象,伴随对象中定义一个函数action和属性data,然后就可以通过Extension.action()和Extension.data使用了,这样在kotlin里很方便,而在Java中我们一般会定义很多静态方法和属性来实现相同的功能

考虑到这样的书写形式,我们也许会想Kotlin的伴随对象是如何实现的,是否和Java中的静态函数和静态属性类似,毕竟调用方式摆在那儿,不这么想都难!

2.开始吃官方的栗子

2.1 码个代码

为了和扩展函数和扩展属性做比较,我们不妨在代码中加入扩展函数和属性的代码,做一个比较;

代码如下:

fun main(args: Array<String>) {
    Extension.action()//Extension的伴生对象函数
    println(Extension.data)//Extension的伴生对象属性

    Extension().fly()//Extension的属性拓展

    Extension.run()//Extension的伴生对象的函数拓展
}

class Extension {
    var variety: String = "origin "

    companion object {
        fun action() {
            println("action")
        }

        val data = "123"
    }

}

fun Extension.Companion.run() {
    println("run with $data")
}

fun Extension.fly() {
    println("fly with $variety")
}

请注意调用方式的区别,尤其是第三行和第四行

其实具体的输出我们不执行也能知道,关键是关注内部是怎么实现的,尤其是编译为class后

2.2 编译为.class

在桌面上vim一个Extension.kt文件,写入上述代码;

然后执行命令

得到.class文件后,我们用jd-jui打开一探究竟

无法执行的请执行以下命令配置环境,然后重试第一步(PS:可能会下载几次都会失败,原因你懂的,如果实在不行,请自行搜索如何copy studio下的文件夹,因为我没试过这种方式..)
$ sudo port install kotlin
2.3 理解伴随对象实现

使用jd-jui打开后我们先看看入口,也就是main函数的编译后的代码:
伴随对象1

我们再看看Extension.class
伴随对象2

可以看到原Kotlin代码和编译后的字节码的区别,用Java的方式理解很简单

  • Extension的伴随对象的函数和属性,编译后创建了一个静态内部类的,然后默认生成一个静态属性,最终编译后就直接引用这个静态属性完成函数和伴随对象的函数和属性调用
  • Extension的扩展属性(扩展函数相同的原理)本质上是通过语言级的装饰器模式修饰的函数(参考第一张图方法)
  • Extension的伴随对象的扩展函数形式同Extension的扩展函数(不要被Extension.Companion所迷惑,==)

对比扩展函数可以发现,伴随对象被编译为了静态内部类(这就是为什么Kotlin伴随对象内不能访问外部类的成员),而扩展函数/属性是通过装饰器模式做了包装,两者实现完全不同;

结语

从本文过程中我们理解了

  • 伴随对象的一般实现形式
  • 伴随对象的语言实现机制
  • 伴随对象与扩展函数/属性的区别

附注:

Kotlin的中文文档可以 戳这里

官方也支持 kotlin在线编程

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值