我們仍在為Kotlin 1.4而奮鬥,但新的預覽版本1.4-M2已蓄勢待發。下面我們將揭曉預覽版的部分改進,我們將在該部落格中引領你去熟悉標準庫的變動。
這是1.4-M2標準庫的更改關鍵字:
- 現有API的改動 例如更新簽名和引入新的常量
- common庫的更多新功能
- Arrays和Collections的新函式
- 屬性代理的改進
儘管Kotlin 1.4-M2尚未釋出,我們仍將其早期版本部署到Kotlin playground,以便你可以嘗試本文中的所有內容。這篇文章中的程式碼示例也可以在新版本上執行。
如果你等不及想要嘗試新版本,訂閱Kotlin部落格的資訊,那麼你將不會錯過釋出日。
common庫的擴充套件
你可以在需要不同平臺(Android、iOS、JVM、JS)之間共享的“通用”程式碼中使用標準庫。我們正在逐步擴充套件common庫,並向其中遷移缺少的功能。
在Kotlin/JVM中,appendln
的早前實現新增了一個依賴於系統的行分隔符(UNIX系統上為\\n
,Windows系統上為\\r\\n
)。但當涉及到通用程式碼,我們認為重要的是保證其行為要獨立於作業系統及底層平臺。這是我們不推薦appendln
,而建議用新的appendLine
函式去代替的原因,該函式始終以單個\\n
作為行終止符:
我們還為陣列的子序列排序新增了新的函式。在此之前,帶fromIndex
和toIndex
引數的sort()僅適用於JVM。現在它是公共函式了,同時還有兩個新的類似函式,它們是reverse()
和sortDescending()
的子序列版本。它們都帶有兩個索引,並像其名字一樣對它們的子序列(包含fromIndex
但不包含toIndex
)進行重新排序:
reverse()
陣列子序列元素順序反轉。sortDescending()
陣列子序列元素降序排列。
collections API的新函式
在1.4-M2中,我們將繼續擴充套件標準庫中的collections API,以涵蓋更多實際案例:
- 一個新的set建立函式
setOfNotNull()
,建立一個由引數中的非null項組成的set。
- 現在序列已支援
shuffled()
了。
onEachIndexed()
和reduceIndexedOrNull()
已分別作為onEach()及reduceOrNull()的副本新增。名稱中帶有Indexed
的集合處理函式,其操作帶有一個索引引數。
runningFold()
和runningReduce()
作為scan()
和scanReduce()
的同義詞引入。而其名稱近似於相關的函式fold()
和reduce()
。而未來scan()
會與runningFold()
一同使用,因為它是該操作的常用名稱。但是實驗性的scanReduce()
將被棄用並且不久後刪除。
現有API的改進
由於Kotlin 1.4是主要的“特性”版本,因此我們為語言新增了新特性,併為標準庫新增了新函式或介面。我們僅在增量版本(如1.3.70)中新增新的experimental宣告。如果你不使用任何實驗性的宣告,而僅僅使用Kotlin 1.3.70編寫程式碼,那麼在Kotlin 1.3.40你的程式碼仍能順利地進行編譯。
特性版本不需要遵循和次要版本一樣的嚴格規則,這意味著如果你使用了新特性或API,則1.3版的Kotlin編譯器可能無法編譯用Kotlin 1.4編寫的程式碼。這讓我們可以透過對API進行一些改動以改進它。我們也認真考慮過向後相容性,以便較早版本的程式碼仍能透過編譯和正常工作。
在Kotlin 1.4,我們讓部分函式的引數能接受可空型別了:
該程式碼無法在Kotlin 1.3透過編譯,因為要求String.toBoolean()
的接收者不可為空。 Kotlin 1.4將接收方更改為可空的字串:String?.toBoolean()
。即便如此,你之前編寫的所有程式碼仍可以在Kotlin 1.4中繼續編譯和執行。
相同的邏輯適用於contentEquals
,contentHashCode
和contentToString
函式的Array
接收器:現在都可以為空。此外,String.format()
現在允許傳遞null
給locale
引數,這種情況下,不會應用任何本地化。
Doubles
和Floats
中定義的以下常量現在是“真”常量:
現在將它們被定義為const
常量,因此你可以將它們用作註解的引數了。
SIZE_BITS
和SIZE_BYTES
是Double
和Float
中的新常量;它們表示二進位制形式下bits或bytes的位數。
請注意,我們還更改了Kotlin/JS中的Float.MAX_VALUE
和Float.MIN_VALUE
值。在以前,它們等於JavaScript的Number.MAX/MIN_VALUE
,或者等價於Double.MAX/MIN_VALUE
,因為Float
本質上等價於Kotlin/JS中的Double
。現在,所有平臺的Float範圍常量都一致了。
maxOf()和minOf()接受可變引數
標準庫中的maxOf()
和minOf()
函式可以求取兩個值中的較大值和較小值。從1.4-M1開始,maxOf()
和minOf()
接受可變引數 (vararg
),從而允許你在任何數字集合或可比較的項上呼叫它們。
屬性代理的改進
在Kotlin中,屬性代理是透過約定而不是介面來工作的:要用作代理的型別必須定義一個運算子,而不是實現所需的介面。這樣可以提供靈活性(因為我們不受特定介面的束縛),但是在許多實際使用場景中,介面會更加方便。
在Kotlin 1.4中,我們使這種互補的介面能更方便地使用:我們引入了一個新的PropertyDelegateProvider
介面,並且ReadWriteProperty
現在繼承了ReadOnlyProperty
。請繼續往下閱讀以瞭解更多詳細資訊。
代理表示式
ReadWriteProperty
和ReadOnlyProperty
介面可方便地定義屬性代理,只需你的自定義類或匿名物件實現了它們:
從1.4開始,ReadWriteProperty
繼承了ReadOnlyProperty
。這使你可以更靈活地使用代理表示式。在我們的示例中,你可以在需要ReadOnlyProperty
的情況下傳遞myDelegate()
的呼叫。
這裡我們要強調的是,“只讀”與Kotlin中的“不可變”不同,類似於只讀列表並非不可變列表。 “只讀”表示“介面僅提供對所涉及物件的只讀訪問”。
提供一個代理
透過使用提供代理的機制,你可以擴充套件建立“代理”物件(將屬性實現代理給該物件的物件)的邏輯。你可以在文件中找到有關其工作方式的詳細資訊。在1.4中,為了使這種機制更加方便,我們新增了一個新的PropertyDelegateProvider
介面。當你不想建立額外的類而更喜歡使用匿名物件時,就可以使用它,類似於上面的myDelegate()
示例中看到的那樣。
代理到另一個屬性
從1.4開始,屬性可以將其getter和setter直接代理給另一個屬性。例如,當你想以向後相容的方式重新命名屬性時,這可能很有用:引入一個新屬性,用@Deprecated
註解一箇舊屬性,並委派其實現。
前面描述的代理屬性編譯的最佳化適用於這種情況。由於代理運算子的實現不使用有關要代理屬性的資訊(oldName
),因此編譯器無需使用該資訊生成KProperty
例項。未來也有可能不為代理(newName
)生成其他KMutableProperty
例項。
如何嘗鮮
所有描敘過的變更都已實裝到Kotlin 1.4-M2預覽,並且你可以透過play.kotl.in線上去嘗試;只需要在設定中選擇1.4-M2版本。
預發行版須知
請注意,向後相容性不保證覆蓋預發行版本。功能和API可能會根據你的反饋在後續版本中進行更改。
分享你的反饋
感謝你在問題跟蹤器中提交的所有錯誤報告。在最終版本釋出之前,我們會盡力解決所有重要問題,避免讓這些問題一直拖延到下一個版本。
歡迎你加入我們Kotlin Slack (在這裡獲取邀請)的#eap頻道,去提問,參與討論以及獲取有關新預覽版本的通知。
Let’s Kotlin!