初見Kotlin
原文連結在我的部落格: 初見Kotlin
前段日子Kotlin
釋出了1.0版,號稱Android界的Swift,一副拯救苦逼Android碼農於水火中的架勢。那麼它有何神奇之處呢?經過一段時間的摸索,Kotlin在我眼中定位為“通吃型”語言,服務端不是問題,還能生成JavaScript,另外又有針對Android開發的增強服務特性。
Kotlin一出世就被拿來跟Scala比較,恰巧Scala也是我喜歡的一門JVM語言。其實,我個人感覺Kotlin並非Scala的小弟,只是說有了val
和var
的表象,給許多開發者這種感覺,但要這麼說的話,Scala的函式/方法定義用def
而Kotlin卻用fun
這又怎麼說呢?此外,Kotlin的伴生物件跟Scala中的概念也區別不小。另一種說法是Kotlin比Scala簡單,也許Kotlin尚未實現Scala中我喜歡的yield
功能,但要從發展角度來看,Kotlin出道時間短,後續要新增的功能應該會層出不窮。Kotlin的用法並不簡單。要說“骨子裡”的像,我寧願覺得Kotlin更像Java
:
- 號稱“100% interoperable with Java™”:使用一段時間的感受是,寫著寫著,就有可能不知不覺中無縫地使用Java程式碼風格,寫完了才恍然大悟......
- 一方面Kotlin新增了大量函式式風格,它的map、filter等等操作比
Java 8
Stream的來得簡潔直接。但隱約感受得到,這只是Kotlin特性中表面且很小的一部分,涉及過多的功能需求時,還是要尋求Java的特性支援。這點不像Scala,Scala是能不用Java原生特性就不用,而Kotlin則是需要用時你用就是了。不知道這是好事還是壞事,但終究看個人偏好吧,對於Java底子較好或較適應Java風格的開發者來說,這則是一個不錯的起點。
上面是我覺得有必要澄清的一些概念。而以下則是Kotlin吸引我研究下去的一些因素:
- Null Safety:別小看這一點,強迫症真能防範大量潛在問題。
- Extension Functions:很喜歡這個特性,即開即用的感覺。
- JetBrains家的東西,還是有些功底的,更重要的是跟聞名遐邇的自家開發工具必然結合緊密。
- 充分考慮Android平臺開發的環境及特性適配,也難怪稱為“Android開發的Swift”。
- 與Java的互操作性:也許會讓大票開發者不感冒,但對我來說再好不過。
以下是Kotlin的一些限制,當然也只是我個人的一些看法:
- 穩定性:尚待提高,特別是REPL工具,動不動就導致退出REPL環境。此外,程式碼中的空行及註釋都會在REPL中引發異常。
- 文件:官方文件比較初級,且資源不多。
- 普及率:小眾。TIOBE從上月起已經納入了Kotlin的觀察,首月排名貌似158位。
整個感受,用這個示例實現來解釋最恰當不過了:
給一個自定義日期類新增Comparison
、Range
及For
迭代功能。
data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int) : Comparable<MyDate> {
override fun compareTo(other: MyDate): Int {
val calendar1: java.util.Calendar = java.util.Calendar.getInstance()
val calendar2: java.util.Calendar = java.util.Calendar.getInstance()
calendar1.set(this.year, this.month - 1, this.dayOfMonth)
calendar2.set(other.year, other.month - 1, other.dayOfMonth)
return if (calendar1.before(calendar2)) -1 else if (calendar1.after(calendar2)) 1 else 0
}
}
class DateRange(val start: MyDate, val end: MyDate): Iterable<MyDate> {
private var _dateRange: MutableList<MyDate> = mutableListOf<MyDate>()
init {
val calendar1: java.util.Calendar = java.util.Calendar.getInstance()
val calendar2: java.util.Calendar = java.util.Calendar.getInstance()
calendar1.set(start.year, start.month - 1, start.dayOfMonth)
calendar2.set(end.year, end.month - 1, end.dayOfMonth)
if (start < end) {
_dateRange.add(MyDate(calendar1.get(java.util.Calendar.YEAR),
calendar1.get(java.util.Calendar.MONTH) + 1,
calendar1.get(java.util.Calendar.DAY_OF_MONTH)))
val days = (calendar2.getTimeInMillis() - calendar1.getTimeInMillis()) / 1000 / 60 /60 /24
for (day in 1..days) {
calendar1.add(java.util.Calendar.DAY_OF_MONTH, 1)
_dateRange.add(MyDate(calendar1.get(java.util.Calendar.YEAR),
calendar1.get(java.util.Calendar.MONTH) + 1,
calendar1.get(java.util.Calendar.DAY_OF_MONTH)))
}
}
}
override operator fun iterator(): Iterator<MyDate> {
return MyDateIterator()
}
inner class MyDateIterator: Iterator<MyDate> {
private var _index: Int = 0
override operator fun hasNext(): Boolean {
return _index != _dateRange.size
}
override operator fun next(): MyDate {
return _dateRange[_index++];
}
}
}
operator fun MyDate.rangeTo(other: MyDate): DateRange {
return DateRange(this, other)
}
測試程式碼:
>>> fun iterateOverDateRange(firstDate: MyDate, secondDate: MyDate, handler: (MyDate) -> Unit) {
... for (date in firstDate..secondDate) {
... handler(date)
... }
... }
>>> iterateOverDateRange(MyDate(2016, 3, 10), MyDate(2016, 3, 14)) { println(it) }
MyDate(year=2016, month=3, dayOfMonth=10)
MyDate(year=2016, month=3, dayOfMonth=11)
MyDate(year=2016, month=3, dayOfMonth=12)
MyDate(year=2016, month=3, dayOfMonth=13)
MyDate(year=2016, month=3, dayOfMonth=14)
>>> iterateOverDateRange(MyDate(2016, 5, 1), MyDate(2016, 5, 5)) { println(it) }
MyDate(year=2016, month=5, dayOfMonth=1)
MyDate(year=2016, month=5, dayOfMonth=2)
MyDate(year=2016, month=5, dayOfMonth=3)
MyDate(year=2016, month=5, dayOfMonth=4)
MyDate(year=2016, month=5, dayOfMonth=5)
>>> iterateOverDateRange(MyDate(2016, 5, 1), MyDate(2016, 5, 1)) { println(it) }
>>> (MyDate(2016, 3, 10)..MyDate(2016, 3, 14)).map { println("${it.year}-${it.month}-${it.dayOfMonth}") }
2016-3-10
2016-3-11
2016-3-12
2016-3-13
2016-3-14
[kotlin.Unit, kotlin.Unit, kotlin.Unit, kotlin.Unit, kotlin.Unit]
>>>
>>> fun checkInRange(date: MyDate, first: MyDate, last: MyDate): Boolean {
... return date in first..last
... }
>>> checkInRange(MyDate(2016, 3, 13), MyDate(2016, 3, 10), MyDate(2016, 3, 14))
true
>>> checkInRange(MyDate(2016, 3, 8), MyDate(2016, 3, 10), MyDate(2016, 3, 14))
false
>>> checkInRange(MyDate(2015, 3, 13), MyDate(2016, 3, 10), MyDate(2016, 3, 14))
false
>>>
結論:
剛好現在看到一個開發者的困惑:“Kotlin讓我感到不安。它離開Java 能玩得起嗎 ?”我覺得Kotlin發展的前提是不離開Java,這個前提沒了,估計Scala、Clojure一樣沒戲——Kotlin本身就是Java形態的增強與補充!
該不該學習Kotlin?——Kotlin就是一門語言,不是什麼“十全大補丸”,但其現在面臨的最急迫任務就是普及與推廣,至少要達到Groovy、Scala或Clojure等“同門師兄弟”的地位,雖然這些個JVM語言的排名也不是很高。“該不該學”這個問題真沒有答案。總之,它就是一門新興的語言而已。
相關文章
- 【Kotlin】初識Kotlin(二)Kotlin
- Kotlin初學者指南Kotlin
- 【Kotlin】初識Kotlin之物件導向Kotlin物件
- 初識Kotlin之集合Kotlin
- Kotlin 初體驗(引) 用kotlin開發安卓Kotlin安卓
- Redis 初見Redis
- Swift初見Swift
- MySQL-初見MySql
- JVM-初見JVM
- RabbitMQ-初見MQ
- Kotlin開發之旅《一》— 初學者Kotlin基礎必備Kotlin
- 分散式-鎖-初見分散式
- 快取初見——EhCache快取
- 初見websocket技術Web
- Kotlin可見性修飾符Kotlin
- 【譯】當 Kotlin 遇見 GradleKotlinGradle
- Kotlin Coroutine(協程): 二、初識協程Kotlin
- 常見Kotlin高頻問題解惑Kotlin
- 在 Android 開發中使用 Kotlin 協程 (一) -- 初識 Kotlin 協程AndroidKotlin
- Kotlin 初嘗之專案實踐總結Kotlin
- Kotlin——初級篇(二):變數、常量、註釋Kotlin變數
- Kotlin——初級篇(一):開發環境搭建Kotlin開發環境
- 我和圖靈的初見圖靈
- Kotlin——初級篇(三):資料型別詳解Kotlin資料型別
- 初學Kotlin——在自定義View裡的應用KotlinView
- Kotlin——初級篇(七):函式基礎總結Kotlin函式
- 當 Kotlin 遇見 RxJava 多資料來源KotlinRxJava
- Scala 學習筆記 (1):初見筆記
- PHP初學者常見問題集PHP
- 初見函數語言程式設計函數程式設計
- go語言初學者常見錯誤Go
- 初學python的常見問題Python
- 初見SpringMVC之資料繫結SpringMVC
- 初見React,一步一個坑React
- 初識javascript的一點點見解JavaScript
- [Shell] awk初學之常見問題
- Kotlin 常見內聯擴充套件函式的使用Kotlin套件函式
- Android遇上Kotlin | 第一部分第一課 : Kotlin若只如初見AndroidKotlin