Kotlin中泛型类的扩展函数
下面我的扩展功能有什么问题
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
并希望实现相同的行为,例如T被推断为Foo <Any>
class Foo { fun <T> T.foo(that: T): T = throw Exception() init { "str" foo 42 } }
这个问题是泛型工作的核心。
class Foo { fun <T> T.foo(that: T): T = throw Exception() init { "str" foo 42 } }
这是有效的,因为编译器可以找到一个适合函数签名和参数的T
:它是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>
不是 Foo<Any>
的子类型,实际上除了Int
,没有其他类型的T
将使得Foo<T>
成为超类型Foo<Int>
。 所以, T
必须是正确的,但它也必须完全相同的逻辑String
(由于第二个参数),所以没有解决方案,该功能是不适用的。
您可以通过在T
创建Foo
协变化来使其工作:
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
您的方法plus
期望参数具有与接收器相同的通用类型参数T
因此,您不能将Foo<String>
添加到Foo<Int>
。
如果你想能够添加所有类型的Foo
,比你需要声明你的扩展功能是这样的:
operator fun <T,R> Foo<T>.plus(that: Foo<R>): Foo<T> = throw Exception()