首页 > 解决方案 > Kotlin 中的协变函数参数

问题描述

我想实现一个函数,它可以选择接受一个 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 类的函数?

标签: genericskotlincovariance

解决方案


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

假设您有一个功能:

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

你可以像这样调用这个函数:

print<Int>(1)

一切都很好。

但是假设String当用户不想指定 `toPrint' 参数时,您希望有一个默认参数。按照您的方法,您将执行以下操作:

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

推荐阅读