内容简介 前面讲了 Kotlin 是如何定义一个类,我们发现与 Java 还是存在很多不同。今天我们来讲解下 Kotlin 中都有什么样的类,以及如何定义呢? 讲解前大家想想 Java 中有什么样的类呢?普通类丶抽象类丶非静态内部类丶静态内部类丶匿名内部类丶枚举类,我想大家应该对这些类都在熟悉不过了吧?Kotlin 中也存在这些类只是定义方式不同罢了,并且 Kotlin 中新增了部分类(密封类 丶 Data类丶单例类)。
静态内部类
Kotlin
中如何定义呢? 我们看看反编译的 Java
代码,可以发现 Kotlin
中默认定义的内部类就是静态内部类(刚好与 Java
相反)。 还发现定义的静态内部类是被 final
修饰的,也就是说不可以被继承的,那如何让其可以继承呢? 通过 open
修饰即可啦。
非静态内部类
Kotlin
中只需要通过 inner
修饰符,修饰内部类即可。 Java
的代码可以清晰的看出内部类,没有被 static
修饰。 匿名内部类
Android
中经常被使用,例如我们经常一个方法的参数接收一个接口的类型或者抽象类对象,我们以前都会直接通过 new
关键词,直接创建一个无名类的对象,并实现其对应方法。 其实匿名内部类,并不是没有名字的。 在编译后也会生成 class
文件,类名会定义成 外部类昵称$N
(这里的N是一个数字,数字依次递增表示多个匿名内部类)。
我们看到 Kotlin
中定义匿名内部类不再是通过 new
关键词来定义了? 而是使用 object
来定义,并且若抽象类具有构造函数,一定要传入对应构造参数。 (大家想想 object 关键词还在那里用到过呢? )
class
文件。
的确是生成了2个 class
文件,奇怪怎么和我说的 外部类昵称$N
结果不一样呢? 我特意在写了一个 Java
类。
接下来,我通过 ApkTool
反编译了下,直接看 smali
文件更为的直接。 看下图 Java
的确是这样命名规则,但是 Kotlin
规则变了 外部类昵称$接收对象昵称$N
(应该是 Kotlin
编译器搞的鬼吧)。
为何纠结这个问题呢? 因为有时候我想反射创建匿名内部类对象的时候,会用到这个知识点。
枚举类
Java
是一样的,并且支持使用 when
语句。 单例类
在 Java
中单例设计模式是常见的一种设计模式了,常见的单例有 懒汉丶饿汉丶枚举单例丶静态内部类单例,以前写单例这种搬砖代码,我都是添加一个代码模板。 Kotlin
语言开发者似乎也头疼这个问题,为我们专门定义了一种单例类。 Kotlin
中只需要通过 object
修饰类即可。
是不是超级简单?那 它属于什么样的单例呢? 我们看下反编译后的 Java
代码,原来是饿汉式单例。 大家试想下 Kotlin
如何定义一个懒汉式的单例呢? (提示:伴生对象
在 Java
中是不是经常定义实体对象呀,然后重写其 get
丶 set
丶 toString
丶 hashCode
丶 equals
等方法。 Kotlin
再也不用这么复杂了,只需要通过 data
修饰类即可。
看下反编译结果:
通过上面的反编译代码,发现还是重写了很多方法,并且定义了 copy
方法。(深拷贝呢? 还是浅拷贝呢?
这里补充下 componentN
方法,这个类似一个操作符重载,后续会 讲到 。 其实在测试用例中,我演示过用法 val(name,time)=play
快速创建了2个 name
和 time
变量,并且将 play
对象中的 component1
和 component2
方法返回值将其赋值。 这个是不是很眼熟呀? 没错集合遍历的时候用到这个点了。
密封类
密封类定义 sealed
修饰,密封类定义有限个数的子类,并且限制定义范围(不包含间接继承,和 Java
中的枚举有异曲同工之处。
密封类与枚举类存在本质区别,密封类是注重子类个数,枚举类注重的是有限对象个数。 那密封类有什么好处呢? 举个例子:用户场景,分为3种用户 普通会员丶 会员丶 超级会员,我们每种会员都有对应的特殊功能,所有的会员都要是 User
的子类。 以前我们可以通过枚举定义这种会员类型,但是不能对其定制特定的方法与属性,在 Kotlin
中可以用密封类来代替。
补充下:在 Kotin1.1
修改了密封类的继承范围,只需要在同一个 kt 文件都可以继承。
知识点: sealed
修饰的类为何不能 new
呢?其实 Kotlin
编译器搞的鬼,将密封类编译成一个抽象类,所以无法直接创建对象。
类的映射 typealias
这是个补充点,为何 放在 类 篇章呢? 因为它和类有一定关系。 还记得集合篇章我说过 Kotlin
并没有重复造轮子,完全使用的 Java
中的集合。 怎么实现的呢? 其实就是通过 typealias
关键词。
其实 typealias
关键词主要在告诉编译器,编译到我定义的 KotlinFile
请给我替换成 File
。
接下来看看, Kotlin
中定义的集合映射吧!大伙想没想过为啥要这样做呢?个人理解为了解耦,假如有一天 Kotlin
想造轮子了,为了保证以前的代码不用更改,只需要修改映射关系即可。
--END--
识别二维码,关注我们