设置Kotlin泛型的默认值

时间:2020-02-04 19:56:39

标签: generics kotlin

我具有此扩展功能:

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尽可能简单。

P.S。 synthetic选项有几个错误,这就是我们使用此惰性绑定的原因是要远离它。

1 个答案:

答案 0 :(得分:2)

Kotlin编译器将始终推断最特定的泛型类型,并且没有“默认”类型参数之类的东西,因此您必须创建额外的功能。您可以使用JvmName批注来解决平台声明崩溃:

fun <T> foo(): T? = null

@JvmName("foo0")
fun foo(): Any? = null

fun main() {
    foo<Nothing>()
    foo()
}
相关问题