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