这个问题是泛型如何工作的核心。
class Foo {
fun <T> T.foo(that: T): T = throw Exception()
init {
"str" foo 42
}
}
这是可行的,因为编译器可以找到T
同时适合函数签名和参数的 a:它是Any
,并且函数变成了这个:
fun Any.foo(that: Any): Any = ...
现在,String
是 的子类型Any
,Int
是 的子类型Any
,所以这个函数适用于参数。
但在你的第一个例子中:
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
:
fun Foo<Any>.plus(that: Foo<Any>): Foo<Any> = ...
现在,在 中Foo
是不变的T
,所以Foo<Int>
不是的子类型,事实上,除此之外没有其他类型会成为的超类型。所以,必须是exact ,但也必须是完全一样的逻辑(因为第二个参数),所以没有解决方案,函数不适用。Foo<Any>
T
Int
Foo<T>
Foo<Int>
T
Int
String
Foo
您可以通过在以下中进行协变来使其工作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
,但如果您对他们没问题,它可以解决您的问题。
查看此链接了解更多详细信息:http: //kotlinlang.org/docs/reference/generics.html