作者 / David Winer, Kotlin 产品经理
有时候一些可读性差、不够明确或者名字太长的类型申明会烦扰代码的 “ 自我表白 ”。这种状况下,能够应用 Kotlin 特地针对这个问题提供的个性: Typealias (本文下称 “ 类型别名 ”)。类型别名能够使您在不减少新类型的状况下,为现有类或函数类型提供代替名称。
类型别名的应用
应用类型别名为函数类型命名:
typealias TeardownLogic = () -> Unit
fun onCancel(teardown : TeardownLogic){ }
private typealias OnDoggoClick = (dog: Pet.GoodDoggo) -> Unit
val onClick: OnDoggoClick
不过要留神这种用法会暗藏传入参数,使可读性变差:
typealias TeardownLogic = () -> Unit
typealias TeardownLogic = (exception: Exception) -> Unit
fun 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 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
}
类型别名为现有类型提供一个更短或更具意义的名称。但如果您要谋求更高的安全性,则创立一个新的类型会比拟适合。