前言
书接上回,上回跟大家聊了下kotlin的一些常用的语法和如何通过将kotlin转换为java代码来深入了解koltin语法的本质,今天我们继续了解一下kotlin的其他一些特性。
其实我在写上一篇文章的时候,介绍的一些方法主要是为了跟大家分享一下,如何去理解kotlin语法糖背后的本质,不过后来想想前面的内容又太单一简单了,因此就继续水一篇文章。我们继续了解一下一下kotlin其他的语法糖。
密封类和枚举类
枚举类我们就不详细展开了,相信大家都很了解。它常常用于定义有限的集合。因此常被我们当做单例和多例模式。
1 | kotlin复制代码enum class Gender{ |
那么什么是密封类呢?刚接触密封类的时候,我还是比较奇怪的,首先我们来看下密封类的使用方式
1 | kotlin复制代码// 首先定义一个密封类,人类 |
在形式上看似比较像,但是这里有一个很大的区别,枚举类里面我们使用的是 == 进行判断,密封类我们是使用is(类似Java的instanceOf),看到这里大家可能已经有一个大致的区分。枚举类定义出来的,已经是类的实例对象,而密封类定义的是类的子类。他们都用于表示限定的类层次结构,但是方式不同。因此,在使用上,我们常常拿枚举当做单例或者多例模式。而密封类常常当做一个被限定子类的集合,但是子类的实例可以有多个,就好比如我们去请求一个接口,返回的结果成功、失败、异常,但是可以有很多次成功、失败、异常。
再回到上面的例子看,枚举里的男性、女性我们通常可以设定为一个属性,而密封类的男性、女性我们设定为一个子类特征集合,他们互不冲突,两者是可以互补的,我们讲上述的例子结合一下。
1 | kotlin复制代码// 首先定义一个密封类, |
我们将密封类和枚举类结合,枚举类的Gender是密封类People的一个性别属性。看到这里,大家基本上就可以分清楚枚举类和密封类的区别了。
我们将上述代码转换成Java代码看一下:
1 | scala复制代码// Gender.java |
看到这里,大家应该就能理解枚举类和密封类的本质区别在哪里了。
我们知道,在kotlin中,枚举类和密封类都是支持when(类似Java的switch-case语句)的判定的。我们来看下以下代码:
1 | kotlin复制代码// 通过枚举类型的判定 |
枚举类型的判定是直接通过when(param) -> value 的方式判定的,而密封类的是通过when(param) -> is value的方式进行的。
kotlin的运算符重载
kotlin和C++一样,是支持运算符重载的,可是Java是没有运算符重载的。那么为什么Java没有运算符重载呢?因为Java的设计者认为,运算符本质上也是函数的调用。没错,其实kotlin的运算符本质上也是方法调用,只不过kotlin的编译器帮助我们能够使用重载之后的运算符进行开发,提高我们的开发效率。
下面,我们来看一个运算符重载的例子
1 | kotlin复制代码// 一个简单的数据类 |
在上述例子当中,我们实现了加法运算符号的重载来计算两个坐标相加的功能。其实例子很简单,我们来简单了解下运算符重载的本质是什么。老规矩,我们看下翻译成Java代码
1 | java复制代码// Point.java |
我们发现,在Java当中,我们的“+”的操作符,被转换成了plus方法,这是kotlin帮我们做的。所以,本质上,kotlin的运算符重载就是方法调用,其实我们使用的block() 亦是如此,他重载了invoke。更多支持重载的运算符,这里就不一一展开了,可以查看kotlin的中文网的说明。
kotlin的解构
在kotlin当中,我们可以将对象的属性赋值给多个新定义的属性,这种被称为kotlin的解构。我们看下下面这段代码
1 | kotlin复制代码data class Human( |
这里是不是觉得好理解,其实本质上应该就是参数的赋值吧。那么究竟是不是呢,我们来看一下Java对应的代码
1 | kotlin复制代码// Deconstruct.java |
那么为什么不是使用getParams的方式,而是要多几个方法呢?这不是多此一举吗?其实不然,不知道大家发现没有,上述的class我使用的是data class,在kotlin当中,data class都会默认生成componentN和copy的方法,原因就是这个,当我们去掉data的,让其变成一个普通的class的时候,我们发现会报如下错误。
我们按照提示,将componentN的方法加上去如下:
我们发现,代码顺利通过。这里我们惊奇的发现,componentN前面有个关键字,是operator,没错,解构的本质就是kotlin的操作符重载,之所以把解构放在操作符重载后面讲就是这个原因。
解构的方式其实我们还可以用在lamda表达式当中,如下所示:
1 | kotlin复制代码fun deconstruct(){ |
其实kotlin帮我们封装了很多的方法,来提升我们的开发效率,比如Collections当中的filter、map都是依靠支持迭代器(Iterator)的扩展函数实现的,因此我们在学习kotlin的语法糖的时候,要找对方法。不过也不是所有的语法糖都能通过java代码可以看出来的,有些很多也是依赖编译器一起实现的,例如协程的原因。那么本次介绍的语法糖就到这里吧。
本文转载自: 掘金