Kotlin 中泛型类的扩展函数 [英] Extension functions for generic classes in Kotlin
问题描述
我下面的扩展函数有什么问题
What's wrong with my extension function below
class Foo<T> {
fun <T> Foo<T>.plus(that: Foo<T>): Foo<T> = throw Exception()
init {
Foo<Int>() + Foo<String>() // A receiver of type Foo<T> is required
}
}
更新
我想知道为什么它与常规扩展函数不同,其中 T 成功地被推断为 Any
并希望实现相同的行为,例如.G.T 被推断为 Foo
I wonder why it's different than regular extension functions, where T successfully gets inferred as Any
and would like to achieve the same behavior, e. g. T to get inferred as Foo<Any>
class Foo {
fun <T> T.foo(that: T): T = throw Exception()
init {
"str" foo 42
}
}
推荐答案
问题是泛型工作的核心.
The issue is at the very heart of how generics work.
class Foo {
fun <T> T.foo(that: T): T = throw Exception()
init {
"str" foo 42
}
}
这是可行的,因为编译器可以找到一个既适合函数签名又适合参数的T
:它是Any
,而函数就变成了这个:
This works, because the compiler can find a T
that fits both the function signature and the arguments: it is Any
, and the function is turned into this one:
fun Any.foo(that: Any): Any = ...
现在,String
是Any
的子类型,Int
是Any
的子类型,所以这个函数适用于参数.
Now, String
is a subtype of Any
, Int
is a subtype of Any
, so this function is applicable to the arguments.
但在你的第一个例子中:
But in your first example:
class Foo<T> {
fun <T> Foo<T>.plus(that: Foo<T>): Foo<T> = throw Exception()
init {
Foo<Int>() + Foo<String>() // A receiver of type Foo<T> is required
}
}
一切都不一样了.没有这样的 T
.让我们天真地尝试Any
:
It's all different. There's no such T
. Let's be naïve and try Any
:
fun Foo<Any>.plus(that: Foo<Any>): Foo<Any> = ...
现在,Foo
在 T
中是 不变的,所以 Foo
是 not Foo
的子类型,实际上除了 Int
之外没有任何类型 T
可以使 Foo<;T>
Foo
的超类型.所以,T
必须完全是 Int
,但它也必须完全是 String
,按照相同的逻辑(因为第二个参数),所以有无解,功能不适用.
Now, Foo
is invariant in T
, so Foo<Int>
is not a subtype of Foo<Any>
, and in fact there's no type T
other than Int
that would make Foo<T>
a supertype of Foo<Int>
. So, T
must be exactly Int
, but it also must be exactly String
by the same logic (because of the second argument), so there's no solution, and the function is not applicable.
您可以通过在 T
中制作 Foo
co-variant 来使其工作:
You could make it work by making Foo
co-variant in T
:
class Foo<out T> {
fun <T> Foo<T>.plus(that: Foo<T>): Foo<T> = throw Exception()
init {
Foo<Int>() + Foo<String>() // A receiver of type Foo<T> is required
}
}
这对 Foo
成员的可能签名施加了一些限制,但如果您同意他们,它就可以解决您的问题.
This imposes some limitations on possible signatures of members of Foo
, but if you are OK with them, it fixes your issue.
查看此链接了解更多详情:http://kotlinlang.org/docs/reference/generics.html
Have a look at this link for more details: http://kotlinlang.org/docs/reference/generics.html
这篇关于Kotlin 中泛型类的扩展函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!