官术网_书友最值得收藏!

3.1 一個簡單的值類型

讓我們深入到代碼庫中,將現有的一些Java代碼轉換為Kotlin,從EmailAddress開始。這是一個值類型,它包含了一個電子郵件地址的兩個部分:

這個類很簡單,它只封裝了兩個字符串,并且沒有提供對本身的操作。即便如此,它還是有很多代碼:

? 值是不可變的,因此該類將其字段聲明為final。

? 有一個靜態工廠方法可以將字符串解析為EmailAddress,它調用了主構造函數。

? 字段在構造函數中初始化。

? 其屬性訪問器方法遵循JavaBean命名約定。

? 該類實現了equals和hashCode方法以確保所有字段相等的兩個EmailAddress值在進行比較時是相等的。

? toString返回(電子郵件地址)標準形式。

代碼的作者們來自Java學院,他們假設我們傳遞、存儲或返回的所有內容都不為空,除非有明確說明。由于它缺少@Nullable注解或參數的空檢查(第4章中將討論可空性),這種約定可能不會在代碼中明確體現。在這個例子中你可以看到,表達一個由兩個其他值組成的值對象所需的樣板代碼量。令人高興的是,IDE為我們生成了equals和hashCode方法。但是如果我們更改類的字段,一定要刪除并重新生成這些方法以避免出現混淆錯誤。

關于Java就說這么多,我們是為Kotlin而來的。那么,如何將Java轉換為Kotlin呢?幸運的是,IntelliJ提供了一個名為“Convert Java File to Kotlin File”的操作,當我們調用它時,IntelliJ會在必要時提示“是否更改其他文件以保持一致”,由于轉換可能會修改整個項目中的文件,所以最好選擇“是”。

確保在將Java代碼轉換為Kotlin之前沒有未提交的更改,以便你可以輕松查看轉換對代碼庫其他部分的影響,并在轉換發生意外時進行回退。

在當前這個例子中,IntelliJ不必更改任何其他文件。它已經用同一目錄中的EmailAdd-ress.kt替換了我們的EmailAddress.java文件,但是:

Kotlin類明顯更加簡潔,因為它在主構造函數中聲明了它的屬性:通過類名后面的參數。標記為val的參數被視為屬性,因此Kotlin主構造函數的定義等同于下面所有這些Java代碼:

主構造函數語法很方便,但它確實會干擾類的可讀性。遵循標準編碼約定的Java類總是以相同的順序定義其元素:類名、超類、接口,然后是類主體、字段、構造函數和方法。這樣可以輕松地瀏覽類并快速找到你感興趣的特征。

找到Kotlin類中的各個部分并不是那么容易。Kotlin類定義有一個header部分,其中包含類名、主構造函數(可以包含參數和/或屬性定義)、超類(也可能是對超類構造函數的調用)和接口。然后,在類的body中有更多的屬性、構造函數、方法和伴生對象。

來自Java世界的我們(Nat和Duncan)一開始肯定會發現Kotlin類更難閱讀,盡管最終我們習慣了,但有時仍然發現很難將Kotlin類格式化以獲得最佳的可讀性,特別是當header部分包含大量代碼時。一種簡單的解決方法是將構造函數參數列表分行放置,我們可以將光標放在參數列表中,使用Alt-Enter和“Put parameters on separate lines”來完成該操作。在header后面添加空行有時也會有所幫助:

Kotlin一處明顯不如Java簡潔的地方是它使用伴生對象來托管靜態狀態和方法,例如本例中的parse()方法。在Kotlin中,我們通常更喜歡使用頂級狀態和函數,而不是這些類范圍的成員。第8章討論了兩者的利弊。

目前有一些使用靜態方法的Java代碼,例如下面的測試類:

伴生對象與@JVMStatic注解結合使用,意味著當我們將Java類轉換為Kotlin時,這部分代碼不必做出改變,因此暫時讓parse保持原樣,我們將在第8章中討論如何重構為頂級函數。

如果你是Kotlin新手,可能想知道getLocalPart()和getDomain()兩個訪問器方法發生了什么。聲明domain屬性會導致編譯器生成一個私有domain字段和一個getDomain()方法,以便Java代碼仍然可以調用它。這是一段用來支持一個營銷計劃的簡單代碼:

可以看到,Java代碼正在通過getDomain()方法訪問domain屬性。反之亦然,當Java類具有顯式的getDomain()方法時,Kotlin代碼可以通過address.domain來調用它。我們將在第11章中更詳細地討論屬性。

到目前為止,將Java類轉換為Kotlin已經為我們節省了14行代碼,但我們的工作還沒有完成。像這樣的值類型非常有用,但要正確地完成這些轉換并保持其正常工作卻非常乏味,以至于Kotlin提供了語言級別上的支持。如果我們用data修飾符標記類,則編譯器會為我們生成所有尚未定義的equals、hashCode和toString方法。這使得EmailAddress類的代碼簡化為:

? 我們不想使用生成的toString()方法,所以定義了自己想要的toString()。

坦率地說,parse方法仍然令人惱火,它占用了這項工作的過多空間。我們將在第9章中最終解決這個問題,不過現在我們已經完成了將EmailAddress這個Java類轉換為Kotlin的工作。

主站蜘蛛池模板: 西乡县| 芮城县| 正安县| 和田市| 衡山县| 庄浪县| 乐清市| 乡城县| 珲春市| 台江县| 辽中县| 澄迈县| 静海县| 鄂托克前旗| 新营市| 阿拉善右旗| 沂南县| 揭阳市| 乌兰县| 敖汉旗| 武威市| 新宾| 碌曲县| 同仁县| 天全县| 眉山市| 汝阳县| 勃利县| 临漳县| 库车县| 沙雅县| 英山县| 浦江县| 桦南县| 桃江县| 常德市| 延庆县| 古丈县| 定结县| 肇州县| 习水县|