kotlin中的启发
开始之前先祭奠下我那块在天国的硬盘,由于Gogo的不慎操作(我也就是强制关机了一下而已啊喂),这块买来只有三个月的硬盘还在换新的路上。
哦,还有秘封活动记录第二话快出了,Gogo又得吃土去买了。
前言
每学一门新的语言,总会从中得到一些启发。
若是没有产生新的想法,那这门语言也就不值得学。
现在许多语言都十分相似,刚接触编程时的新鲜感似乎早就不见。
然而Gogo在学Kotlin时却产生了“哇,这才是学习一门语言”的想法。
归根到底,这是由于Kotlin诸多的语法特性,极大的丰富了Gogo的见识。
本文并非kotlin的教程,仅仅是谈论kotlin对我的启发。
语句即是表达式
这一条Gogo很早以前便听说过一二,毕竟有不少人在说Lisp怎么怎么好,Gogo本身也对此有些兴趣。没想到却在kotlin中首次学到这种语法。
例如Kotlin中的 If 既可以是语句也可以是表达式。
1 | //语句 |
每一个代码块的最后一行将会作为表达式的结果。
还有个 when 语法替代了 switch ,并且看起来更加简洁。
1 | b = when(a) { |
甚至函数的返回值也可以用表达式简写
1 | fun b(a: Int): Int = when(a) { |
那么表达式到底有什么意义?可以使代码更加清晰,书写、阅读更加方便。
用lambda扩展语法
kotlin允许我们用lambda函数制造新的语法。
lambda早已经不是什么稀奇的物种,但是kotlin允许将最后一个lambda写在函数外面,这就为创造新的表达方式提供可能
1 | fun <T> lock(lock: Lock, body: () -> T): T { |
用这种方式就能把一些常用的句式封装起来。
既可以避免失误,还让代码更加清晰易懂。还有下面这个,可读性很好。
1 | fun <T> unless(condition: Boolean, body: () -> Unit): Unit { |
扩展函数扩充对象方法
在kotlin中可以为别的类添加方法。
这是Gogo第一次见到能给别的类添加方法,感觉十分新奇。
例如 KotlinTest 中可以用这种方法写简单的测试。
1 | class StringSpecExample : StringSpec() { |
重点是”should add”那一行,那行实际上是一个扩展函数调用。
由于本文并非讨论这种语法的实现方式,因此我不介绍它的实现。
这种调用的实现原理大概是编译成这样。
1 | fun stringInvoke(str: String, body: () -> Unit): Unit { |
虽然明白原理后知道了仍然只是个语法糖,但是初看却让我觉得十分给力。
空安全
空安全我也是第一次在kotlin中见到。空指针异常几乎是最常见的异常,而kotlin试图消灭空指针。
kotlin中每种类型都可能指定能不能为空,例如 String
表示非空的String,而 String?
表示允许为null的String。对于可能为空值的类型,kotlin强制要求判断是否为空。
kotlin还有一些其他的语法来操作null
1 | var str: String? // str 是一个可能为null的字符串 |
值得一提的是判断后还会有自动的类型转换,也是个十分好用的功能。
1 | val a: Int |
启发
虽然kotlin看上去有一堆语法特性,然而仔细思考一下就能发现全是语法糖,实际上与其他的语言并没有什么本质区别。
但它让我用一种新的方式思考代码。
我很早以前就听说过 “代码是写给人来读的,只是顺带让机器执行”
这个道理。学了Kotlin后我更是深有体会。
那么多新奇的语法,只需要在编译的时候处理一下就能支持,既然这样,就应该致力于创造一门语法简洁、逻辑清晰、功能丰富的语言。
对比Kotlin和Java,这点尤其突出。虽然我一开始学的正是Java,但现在已经很少写了。
为何?有了Kotlin这么方便的语言,为什么要去写Java那繁杂、笨拙的语法?
反正编译以后功能完全相同,还能相互兼容,为什么要花更多的时间浪费在写一长串代码上,而不是思考上?
我认为Kotlin的做法很好,让代码尽量简洁易读,其他的工作都交给编译器去做。
学kotlin的过程中,我这个低端的Java程序员也很容易看出,kotlin的许多改进都是Java的痛处。作为目前TIOBE上长期排名第一的语言,Java固然强大,但也有很多的问题。而kotlin就像是根据它的缺陷改进出来的一门理想的语言。
kotlin中一些理念来自于总结Java以及其他编程语言的经验,
还有一些可能来自Lisp,也许我是应该去见识见识Lisp这门充满传奇色彩的语言了。