Kotlin Vocabulary | 类型别名 typealias

Kotlin Vocabulary | 类型别名 typealias

作者 / 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
}

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

版权声明

禁止一切形式的转载-禁止商用-禁止衍生 申请授权

脉脉不得语
脉脉不得语
Zhengzhou Website
Android Developer | https://androiddevtools.cn and https://androidweekly.io WebMaster | GDG Zhengzhou Funder & Ex Organizer | http://Toast.show(∞) Podcast Host

你已经成功订阅到 Android 开发技术周报
太棒了!接下来,完成检验以获得全部访问权限 Android 开发技术周报
欢迎回来!你已经成功登录了。
Unable to sign you in. Please try again.
成功!您的帐户已完全激活,您现在可以访问所有内容。
Error! Stripe checkout failed.
Success! Your billing info is updated.
Error! Billing info update failed.