(速報)Kotlin1.4-M2標準庫的改進

kotliner發表於2020-05-26

我們仍在為Kotlin 1.4而奮鬥,但新的預覽版本1.4-M2已蓄勢待發。下面我們將揭曉預覽版的部分改進,我們將在該部落格中引領你去熟悉標準庫的變動。

這是1.4-M2標準庫的更改關鍵字:

儘管Kotlin 1.4-M2尚未釋出,我們仍將其早期版本部署到Kotlin playground,以便你可以嘗試本文中的所有內容。這篇文章中的程式碼示例也可以在新版本上執行。

如果你等不及想要嘗試新版本,訂閱Kotlin部落格的資訊,那麼你將不會錯過釋出日。

common庫的擴充套件

你可以在需要不同平臺(Android、iOS、JVM、JS)之間共享的“通用”程式碼中使用標準庫。我們正在逐步擴充套件common庫,並向其中遷移缺少的功能。

在Kotlin/JVM中,appendln的早前實現新增了一個依賴於系統的行分隔符(UNIX系統上為\\n,Windows系統上為\\r\\n)。但當涉及到通用程式碼,我們認為重要的是保證其行為要獨立於作業系統及底層平臺。這是我們不推薦appendln,而建議用新的appendLine函式去代替的原因,該函式始終以單個\\n作為行終止符:

我們還為陣列的子序列排序新增了新的函式。在此之前,fromIndextoIndex引數的sort()僅適用於JVM。現在它是公共函式了,同時還有兩個新的類似函式,它們是reverse()sortDescending()的子序列版本。它們都帶有兩個索引,並像其名字一樣對它們的子序列(包含fromIndex但不包含toIndex)進行重新排序:

  • reverse() 陣列子序列元素順序反轉。
  • sortDescending() 陣列子序列元素降序排列。

collections API的新函式

在1.4-M2中,我們將繼續擴充套件標準庫中的collections API,以涵蓋更多實際案例:

  • 一個新的set建立函式setOfNotNull(),建立一個由引數中的非null項組成的set。
  • 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中繼續編譯和執行。

相同的邏輯適用於contentEqualscontentHashCodecontentToString函式的Array接收器:現在都可以為空。此外,String.format()現在允許傳遞nulllocale引數,這種情況下,不會應用任何本地化。

DoublesFloats中定義的以下常量現在是“真”常量:

現在將它們被定義為const常量,因此你可以將它們用作註解的引數了。

SIZE_BITSSIZE_BYTESDoubleFloat中的新常量;它們表示二進位制形式下bits或bytes的位數。

請注意,我們還更改了Kotlin/JS中的Float.MAX_VALUEFloat.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。請繼續往下閱讀以瞭解更多詳細資訊。

代理表示式

ReadWritePropertyReadOnlyProperty介面可方便地定義屬性代理,只需你的自定義類或匿名物件實現了它們:

從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!

相關文章