Kotlin 中的协变函数参数

Covariant function parameter in Kotlin

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

在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 的任何子 class,但在上面的示例中,我收到一条警告说

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

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

这与方差无关。这是您尝试使用泛型的方式的问题。

假设你有一个函数:

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)
}

我现在不明白为什么会这样,但您只需要将其转换为 Class<T>。将您的功能更改为此。

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

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

更新:

你也可以写扩展函数

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

你可以这样使用它

MainActivity::class.java.onComplete()

和默认 class

null.onComplete()

试试这个:

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