我有这个扩展功能:
fun <T : View> Activity.bind(idRes: Int): Lazy<T> = lazy { findViewById<T>(idRes) }
如您所见,我的通用
T
应该是 View
或后代。每当我想使用它来获取 View 后代时,我都会执行以下选项之一:
val textView1 by bind<TextView>(R.id.text_view_1)
val textView2: TextView by bind(R.id.text_view_2)
很不错,但是现在让我们看看问题,有时我不需要具体的类型,我只需要View,例如当我想设置一个点击监听器时,所以我必须这样做:
val view1 by bind<View>(R.id.view_1)
val view2: View by bind(R.id.view_2)
我想知道一种删除显式类型
View
的方法, 让 kotlin 编译器看到它是我定义后的默认值 T : View
, 是否可以?换句话说,我想要这个:
val textView1 by bind<TextView>(R.id.text_view_1)
val textView2: TextView by bind(R.id.text_view_2)
val view by bind(R.id.view_xyz) // kotlin compiler understands it is a View
我确实尝试过:
fun Activity.bind(idRes: Int): Lazy<View> = lazy { findViewById<View>(idRes) }
fun <T : View> Activity.bind(idRes: Int): Lazy<T> = lazy { findViewById<T>(idRes) }
但我得到了:
Platform declaration clash: The following declarations have the same JVM signature
由于泛型类型删除,什么是有意义的……
我想知道一个不涉及其他方法的解决方案,如
fun Activity.bindView...
因为我想让 API 尽可能简单。附言
synthetic
选项有几个错误,这就是我们使用这个惰性绑定(bind)的原因是远离它。
最佳答案
Kotlin 编译器总是会推断出最具体的泛型类型,并且没有“默认”类型参数之类的东西,因此您必须创建额外的函数。您可以使用 JvmName
解决平台声明崩溃的注释:
fun <T> foo(): T? = null
@JvmName("foo0")
fun foo(): Any? = null
fun main() {
foo<Nothing>()
foo()
}
关于generics - 为 kotlin 泛型设置默认值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60064683/