作者 / David Winer, Kotlin 产品经理

有时候一些可读性差、不够明确或者名字太长的类型申明会烦扰代码的 "自我表白"。这种状况下,能够应用 Kotlin 特地针对这个问题提供的个性: Typealias (本文下称 "类型别名")。类型别名能够使您在不减少新类型的状况下,为现有类或函数类型提供代替名称。

类型别名的应用

应用类型别名为函数类型命名:

typealias TeardownLogic = () -> Unitfun onCancel(teardown : TeardownLogic){ }private typealias OnDoggoClick = (dog: Pet.GoodDoggo) -> Unitval onClick: OnDoggoClick

不过要留神这种用法会暗藏传入参数,使可读性变差:

typealias TeardownLogic = () -> Unittypealias TeardownLogic = (exception: Exception) -> Unitfun onCancel(teardown : TeardownLogic){      // 无奈轻易通晓能够从 TeardownLogic 失去什么信息}

类型别名有助于缩短较长的泛型类名:

typealias Doggos = List<Pet.GoodDoggo>fun train(dogs: Doggos){ ... }

应用类型别名时,须要思考是否有必要这么做: 在这里应用类型别名真的会让您的代码意义更明确、可读性更好吗?

思考一下,应用类型别名是否使您的代码变得更易懂

如果您正应用的某个类名称很长,您能够应用类型别名来缩短它:

typealias AVD = AnimatedVectorDrawable

在此示例中,应用 导入别名 (import alias) 会更加适合:

import android.graphics.drawable.AnimatedVectorDrawable as AVD

更实用的场景是: 如果在代码中呈现了来自不同包的雷同类名,能够应用导入别名来打消这样的歧义:

import io.plaidapp.R as appRimport io.plaidapp.about.R

因为类型别名须要在类的内部申明,所以应用时您须要思考束缚它们的可见性。

在多平台工程中应用类型别名

在应用 Kotlin 开发 多平台工程 时,您能够在公共代码 (common code) 中写一个接口,并在相应的平台代码中实现这个接口。Kotlin 提供了 "理论申明" (actual declarations) 和 "预期申明" (expected declarations) 的机制来简化这种操作。在公共代码中申明的接口为预期申明,应用 expect 关键字;在相应的平台代码中的扩大为理论申明,应用 actual 关键字。如果平台代码中曾经实现了公共代码中的某个接口,并且所有冀望办法的签名统一时,您能够应用类型别名将理论申明的类型名称映射到冀望类型上:

expect annotation class Testactual typealias Test = org.junit.Test

工作原理

类型别名不会引入新的类型。例如,反编译 train 和 play 办法后,能够看到传入参数仅应用了 List 类型:

// Kotlintypealias 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 = Longfun pet(dogId: DogId) { … }fun usage() {    val cat = Cat(1L)    pet(cat.catId) // compiles}

类型别名为现有类型提供一个更短或更具意义的名称。但如果您要谋求更高的安全性,则创立一个新的类型会比拟适合。