做者 / David Winer, Kotlin 產品經理html
有時候一些可讀性差、不夠明確或者名字太長的類型聲明會干擾代碼的 "自我表達"。這種狀況下,可使用 Kotlin 特別針對這個問題提供的特性: Typealias (本文下稱 "類型別名")。類型別名可使您在不增長新類型的狀況下,爲現有類或函數類型提供替代名稱。android
使用類型別名爲函數類型命名:安全
typealias TeardownLogic = () -> Unit fun onCancel(teardown : TeardownLogic){ } private typealias OnDoggoClick = (dog: Pet.GoodDoggo) -> Unit val onClick: OnDoggoClick
不過要注意這種用法會隱藏傳入參數,使可讀性變差:app
typealias TeardownLogic = () -> Unit typealias TeardownLogic = (exception: Exception) -> Unit fun onCancel(teardown : TeardownLogic){ // 沒法輕易知曉能夠從 TeardownLogic 獲得什麼信息 }
類型別名有助於縮短較長的泛型類名:函數
typealias Doggos = List<Pet.GoodDoggo> fun train(dogs: Doggos){ ... }
使用類型別名時,須要思考是否有必要這麼作: 在這裏使用類型別名真的會讓您的代碼意義更明確、可讀性更好嗎?spa
思考一下,使用類型別名是否使您的代碼變得更易懂code
若是您正使用的某個類名稱很長,您可使用類型別名來縮短它:orm
typealias AVD = AnimatedVectorDrawable
在此示例中,使用 導入別名 (import alias) 會更加合適:htm
import android.graphics.drawable.AnimatedVectorDrawable as AVD
更適用的場景是: 若是在代碼中出現了來自不一樣包的相同類名,可使用導入別名來消除這樣的歧義:blog
import io.plaidapp.R as appR import io.plaidapp.about.R
因爲類型別名須要在類的外部聲明,因此使用時您須要考慮約束它們的可見性。
在使用 Kotlin 開發 多平臺工程 時,您能夠在公共代碼 (common code) 中寫一個接口,並在相應的平臺代碼中實現這個接口。Kotlin 提供了 "實際聲明" (actual declarations) 和 "預期聲明" (expected declarations) 的機制來簡化這種操做。在公共代碼中聲明的接口爲預期聲明,使用 expect 關鍵字;在相應的平臺代碼中的擴展爲實際聲明,使用 actual 關鍵字。若是平臺代碼中已經實現了公共代碼中的某個接口,而且全部指望方法的簽名一致時,您可使用類型別名將實際聲明的類型名稱映射到指望類型上:
expect annotation class Test actual typealias Test = org.junit.Test
類型別名不會引入新的類型。例如,反編譯 train 和 play 方法後,能夠看到傳入參數僅使用了 List 類型:
// Kotlin typealias Doggos = List<Pet.GoodDoggo> fun train(dogs: Doggos) { ... } fun play(dogs: Doggos) { ... } // 反編譯後 Java 代碼 public static final void train(@NotNull List dogs) { … } public static final void play(@NotNull List dogs) { … }
類型別名不會引入新的類型
所以,您不該該依賴類型別名作編譯類型檢查,而應該使用一個不一樣的類型或者內聯類。例如,下面的方法中,須要傳入一個長整型參數:
fun play(dogId: Long)
爲長整型取一個別名,並不能防止您傳入一個錯的 id:
typealias DogId = Long fun pet(dogId: DogId) { … } fun usage() { val cat = Cat(1L) pet(cat.catId) // compiles }
類型別名爲現有類型提供一個更短或更具意義的名稱。但若是您要追求更高的安全性,則建立一個新的類型會比較合適。