kotlin - 为什么我必须输入这个 Kotlin 代码?
问题描述
interface Foo<T: Bar> {
fun example(bar: T)
}
interface Bar
class Bar1 : Bar
class Bar2 : Bar
class FooEx1 : Foo<Bar1> {
override fun example(bar: Bar1) { }
}
class FooEx2 : Foo<Bar2> {
override fun example(bar: Bar2) { }
}
// Won't compile
// Even though FooEx1 and FooEx2 *are* Foo<Bar>
class ExampleDoesntCompile {
val collection = mutableListOf<Foo<Bar>>().apply {
this.add(FooEx1())
this.add(FooEx2())
}
}
// Will compile
// But have to cast FooEx1 and FooEx2 to Foo<Bar>
class ExampleDoesCompileButRequiresCast {
val collection = mutableListOf<Foo<Bar>>().apply {
this.add(FooEx1() as Foo<Bar>)
this.add(FooEx2() as Foo<Bar>)
}
}
因此,例如,我可以声明 Foo 的参数化类型为out
,但随后我得到函数的编译错误example
:
interface Foo<out T: Bar> {
fun example(bar: T)
}
错误:Type parameter T is declared as 'out' but occurs in 'in' position in type T
解决方案
因为 Java / Kotlin 中的泛型类型默认是不变的。方差
interface Foo<out T: Bar>
如果您不能使其成为协变的,则使列表项成为协变的
val collection = mutableListOf<Foo<out Bar>>().apply {
this.add(FooEx1())
this.add(FooEx2())
}
//or val collection = mutableListOf(FooEx1(), FooEx2())
推荐阅读
- python - 您是否必须在 MS Azure VM 上运行的 python 代码中包含多处理?
- android - 反对在 Android 上直接使用 javax.crypto
- reactjs - 如何通过 Vercel 或 heroku 部署 React 网站?
- python - 每次列中的字符串值更改时如何拆分数据框?
- react-native - React Native 和 Flutter 之间的更好选择(Dart)
- wordpress - htaccess 301 仅重定向根目录,但排除所有文件和子文件夹,但有例外
- php - nginx 不为 ingress-nginx 后面的 PHP 应用程序提供 JS、CSS 文件
- ruby-on-rails - 从 ruby gem firebase 实时数据库中过滤数据
- c# - NEST Elastic Search - 用空格查询一个词
- amazon-web-services - Cron 表达式 Aws 在 EventBridge(Cloudwatch 触发器)启用后每 5 分钟运行一次