• 推荐使用 Kotlin 关键字 Reified


    reified:使抽象的东西更加具体或真实,非常推荐 Android 开发使用这个关键字。本文介绍 3 点特别的使用方式如下:

    1. 不再需要传参数 clazz

    大部分的文章讲解 reified 的使用,都有提到这个点,比如我们定义实现一个扩展函数启动 Activity,一般都需要传 Class 参数:

    1. // Function
    2. private fun Activity.startActivity(context: Context, clazz: Class<T>) {
    3. startActivity(Intent(context, clazz))
    4. }
    5. // Caller
    6. startActivity(context, NewActivity::class.java)

    reified 方式

    使用 reified,通过添加类型传递简化泛型参数

    1. // Function
    2. inline fun <reified T : Activity> Activity.startActivity(context: Context) {
    3. startActivity(Intent(context, T::class.java))
    4. }
    5. // Caller
    6. startActivity(context)

    2. 不安全的转换

    Kotlin 中, 使用安全转换操作符 as?,它可以在失败时返回 null。实现如下函数,我们认为会安全地获取数据或返回 null

    1. // Function
    2. fun Bundle.getDataOrNull(): T? {
    3. return getSerializable(DATA_KEY) as? T
    4. }
    5. // Caller
    6. val bundle: Bundle? = Bundle()
    7. bundle?.putSerializable(DATA_KEY, "Testing")
    8. val strData: String? = bundle?.getDataOrNull()
    9. val intData: Int? = bundle?.getDataOrNull() // Crash

    然而,如果获得的数据不是它期望的类型,这个函数会出现 crash。 因此为了安全获取数据,修改之前的函数如下:

    1. // Function
    2. fun Bundle.getDataOrNull(clazz: Class<T>): T? {
    3. val data = getSerializable(DATA_KEY)
    4. return if (clazz.isInstance(data)) {
    5. data as T
    6. } else {
    7. null
    8. }
    9. }
    10. // Caller
    11. val bundle: Bundle? = Bundle()
    12. bundle?.putSerializable(DATA_KEY, "Testing")
    13. val strData: String? = bundle?.getDataOrNull(String::class.java)
    14. val intData: Int? = bundle?.getDataOrNull(String::class.java) // Null

    这种写法不太友好,不仅在实现函数的方式上,而且还需要传递额外的 clazz 参数。

    reified 方式

    使用 reified,简化泛型参数和保证 as? 类型转换安全性

    1. // Function
    2. private inline fun <reified T> Bundle.getDataOrNull(): T? {
    3. return getSerializable(DATA_KEY) as? T
    4. }
    5. // Caller
    6. val bundle: Bundle? = Bundle()
    7. bundle?.putSerializable(DATA_KEY, "Testing")
    8. val strData: String? = bundle?.getDataOrNull()
    9. val intData: Int? = bundle?.getDataOrNull() // Null

    3. 不同的返回类型函数重载

    实现一个函数计算 DP 到像素,并返回一个 Int 或 Float。这种情况就会想到函数重载,如下所示:

    1. fun Resources.dpToPx(value: Int): Float {
    2. return TypedValue.applyDimension(
    3. TypedValue.COMPLEX_UNIT_DIP,
    4. value.toFloat(), displayMetrics)
    5. }
    6. fun Resources.dpToPx(value: Int): Int {
    7. val floatValue: Float = dpToPx(value)
    8. return floatValue.toInt()
    9. }

    但是,这将导致编译时出错。原因是,函数重载方式只能根据参数计数和类型不同,而不能根据返回类型。

    reified 方式

    使用 reified,可以实现不同的返回类型函数重载

    1. inline fun <reified T> Resources.dpToPx(value: Int): T {
    2. val result = TypedValue.applyDimension(
    3. TypedValue.COMPLEX_UNIT_DIP,
    4. value.toFloat(), displayMetrics)
    5. return when (T::class) {
    6. Float::class -> result as T
    7. Int::class -> result.toInt() as T
    8. else -> throw IllegalStateException("Type not supported")
    9. }
    10. }
    11. // Caller
    12. val intValue: Int = resource.dpToPx(64)
    13. val floatValue: Float = resource.dpToPx(64)

    总结:从上面的3个例子中,很明显 reified 使 Kotlin 用起来更加友好。如果还有其他场景使用 reified 的方法,欢迎分享。

  • 相关阅读:
    Design Compiler工具学习笔记(1)
    CPSC发布关于亚马逊含有纽扣电池或硬币电池产品的相关规则标准!UL4200A
    Golang 必知必会Go Mod命令
    C++核心编程
    Smartbi电子表格故事之高效营销活动后的自助数据分析
    多线程_进程与线程
    排序算法复杂度
    实现安全的服务通信:探索如何使用服务网格来确保服务间的安全通信
    简易SSM框架转账
    腾讯大佬的“百万级”MySQL笔记,基础+优化+架构一篇搞定,秋招必看系列!
  • 原文地址:https://blog.csdn.net/Goals1989/article/details/126964612