reified
:使抽象的东西更加具体或真实,很是推荐 Android 开发使用这个关键字。本文介绍 3 点特别的使用方式以下:java
大部分的文章讲解 reified
的使用,都有提到这个点,好比咱们定义实现一个扩展函数启动 Activity,通常都须要传 Class<T>
参数:安全
// Function private fun <T : Activity> Activity.startActivity(context: Context, clazz: Class<T>) { startActivity(Intent(context, clazz)) } // Caller startActivity(context, NewActivity::class.java) 复制代码
使用 reified
,经过添加类型传递简化泛型参数markdown
// Function inline fun <reified T : Activity> Activity.startActivity(context: Context) { startActivity(Intent(context, T::class.java)) } // Caller startActivity<NewActivity>(context) 复制代码
Kotlin 中, 使用安全转换操做符 as?
,它能够在失败时返回 null。实现以下函数,咱们认为会安全地获取数据或返回 nullapp
// Function fun <T> Bundle.getDataOrNull(): T? { return getSerializable(DATA_KEY) as? T } // Caller val bundle: Bundle? = Bundle() bundle?.putSerializable(DATA_KEY, "Testing") val strData: String? = bundle?.getDataOrNull() val intData: Int? = bundle?.getDataOrNull() // Crash 复制代码
然而,若是得到的数据不是它指望的类型,这个函数会出现 crash。 所以为了安全获取数据,修改以前的函数以下:函数
// Function fun <T> Bundle.getDataOrNull(clazz: Class<T>): T? { val data = getSerializable(DATA_KEY) return if (clazz.isInstance(data)) { data as T } else { null } } // Caller val bundle: Bundle? = Bundle() bundle?.putSerializable(DATA_KEY, "Testing") val strData: String? = bundle?.getDataOrNull(String::class.java) val intData: Int? = bundle?.getDataOrNull(String::class.java) // Null 复制代码
这种写法不太友好,不只在实现函数的方式上,并且还须要传递额外的 clazz
参数。spa
使用 reified
,简化泛型参数和保证 as?
类型转换安全性code
// Function private inline fun <reified T> Bundle.getDataOrNull(): T? { return getSerializable(DATA_KEY) as? T } // Caller val bundle: Bundle? = Bundle() bundle?.putSerializable(DATA_KEY, "Testing") val strData: String? = bundle?.getDataOrNull() val intData: Int? = bundle?.getDataOrNull() // Null 复制代码
实现一个函数计算 DP 到像素,并返回一个 Int 或 Float。这种状况就会想到函数重载,以下所示:orm
fun Resources.dpToPx(value: Int): Float { return TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, value.toFloat(), displayMetrics) } fun Resources.dpToPx(value: Int): Int { val floatValue: Float = dpToPx(value) return floatValue.toInt() } 复制代码
可是,这将致使编译时出错。缘由是,函数重载方式只能根据参数计数和类型不一样,而不能根据返回类型。开发
使用 reified
,能够实现不一样的返回类型函数重载get
inline fun <reified T> Resources.dpToPx(value: Int): T { val result = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, value.toFloat(), displayMetrics) return when (T::class) { Float::class -> result as T Int::class -> result.toInt() as T else -> throw IllegalStateException("Type not supported") } } // Caller val intValue: Int = resource.dpToPx(64) val floatValue: Float = resource.dpToPx(64) 复制代码
从上面的3个例子中,很明显 reified
使 Kotlin 用起来更加友好。若是还有其余场景使用 reified
的方法,欢迎分享。