Yar*_*lav 11 generics kotlin kotlin-extension
我的扩展功能在下面有什么问题
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
}
}
Run Code Online (Sandbox Code Playgroud)
更新
我想知道为什么它与常规扩展函数不同,其中T成功地被推断为Any并且想要实现相同的行为,例如T被推断为Foo <Any>
class Foo {
fun <T> T.foo(that: T): T = throw Exception()
init {
"str" foo 42
}
}
Run Code Online (Sandbox Code Playgroud)
And*_*lav 19
问题是仿制药如何运作的核心问题.
class Foo {
fun <T> T.foo(that: T): T = throw Exception()
init {
"str" foo 42
}
}
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为编译器可以找到T适合函数签名和参数的东西:它是Any,并且函数变成了这个:
fun Any.foo(that: Any): Any = ...
Run Code Online (Sandbox Code Playgroud)
现在,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
}
}
Run Code Online (Sandbox Code Playgroud)
这都是不同的.没有这样的T.让我们天真并尝试Any:
fun Foo<Any>.plus(that: Foo<Any>): Foo<Any> = ...
Run Code Online (Sandbox Code Playgroud)
现在,Foo是不变的T,所以Foo<Int>是不是一个亚型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
}
}
Run Code Online (Sandbox Code Playgroud)
这对成员的可能签名施加了一些限制Foo,但是如果你对它们没问题,它会修复你的问题.
有关更多详细信息,请查看此链接:http://kotlinlang.org/docs/reference/generics.html
小智 6
我认为 Andrey Breslaw 接受的答案是正确的,但提供了不正确的解决方案。
编译器只需要被告知为提供的泛型类型参数推断公共超类型,即,只要 Foo 的泛型类型参数共享一个公共超类型(它们总是会),就使用它。喜欢:
operator fun <T, R: T, S: T> Foo<R>.plus(that: Foo<S>): Foo<T> = throw Exception()
Run Code Online (Sandbox Code Playgroud)
现在,如果类型不匹配,则返回的 Foo 的结果泛型类型参数将根据需要进行扩展,但操作本身是合法的,不会引入协方差。
| 归档时间: |
|
| 查看次数: |
7161 次 |
| 最近记录: |