Kotlin中的协变函数参数

时间:2019-07-12 14:23:52

标签: generics kotlin covariance

我想实现一个函数,该函数可以选择接受Activity类并重定向到该类。如果未提供任何类,则将使用默认值。

在Java中我会做

public void onComplete(@Nullable Class<? extends Activity> redirectTarget) {
    if (redirectTarget == null) redirectTarget = DefaultActivity.class;
    ContextCompat.startActivity(context, new Intent(context, redirectTarget), null);
}

现在,我在Kotlin中尝试了以下方法:

fun <T : Activity> onComplete(redirectTarget: Class<in T> = DefaultActivity::class.java) {
    ContextCompat.startActivity(context, Intent(context, redirectTarget), null)
}

我认为in T可以接受参数中T的任何子类,但是在上面的示例中,我收到警告说

Type missmatch. 
Expected: Class <in T>
Found: Class<DefaultActivity>

如何实现接受任何Activity类的函数?

3 个答案:

答案 0 :(得分:2)

这与差异无关。这与您尝试使用泛型有关。

假设您有一个功能:

fun <T> print(toPrint: T) = println(toPrint.toString())

您可以这样调用此函数:

print<Int>(1)

一切都很好。

但是,假设用户不想指定“ toPrint”参数时,您想要一个默认的String参数。按照您的方法,您会这样做:

fun <T> print(toPrint: T = "") = println(toPrint.toString())

在一个合法的世界中,如果调用指定类型而不是参数的函数会发生什么?例如:

print<Int>()

默认参数的类型与呼叫站点的类型不匹配。

那么如何解决您的问题?
事实证明,您甚至不需要通用函数:

fun onComplete(redirectTarget: Class<out Activity> = DefaultActivity::class.java) {
    ContextCompat.startActivity(context, Intent(context, redirectTarget), null)
}

答案 1 :(得分:0)

我现在不知道为什么会这样,但是您只需要将其强制转换为Class<T>。将功能更改为此。

fun <T : Activity> onComplete(redirectTarget: Class<in T> = DefaultActivity::class.java as Class<T>) {
    ContextCompat.startActivity(context, Intent(context, redirectTarget), null)
}

我只需在as Class<T>输入的末尾添加onComplete

更新:

您还可以编写扩展功能

fun Class<out Activity>?.onComplete() {
    ContextCompat.startActivity(context, Intent(context, this ?: DefaultActivity::class.java), null)
}

您可以像这样使用它

MainActivity::class.java.onComplete()

和默认班级

null.onComplete()

答案 2 :(得分:0)

尝试这个:

fun onComplete(redirectTarget:Class<out Activity> = DefaultActivity::class.java){
    ContextCompat.startActivity(context, Intent(context, redirectTarget), null)
}