Kotlin泛型超/儿童班

试图使用泛型类,但有以下问题,即:

类型不匹配:推断的类型是ChildClass但是SuperClass<SuperType>是预期的

 open class SuperClass<T> where T: SuperType { fun modifySomething(input: T): T { input.someValue.inc() return input } } open class SuperType { val someValue: Int = 0 } class ChildClass : SuperClass<ChildType>() class ChildType: SuperType() { fun getModifiedValue(): Int { return someValue } } class TestEnvironment { fun testType(superClass: SuperClass<SuperType>) { // do something with superClass } fun itDoesntWork() { testType(ChildClass()) // compilation error } } 

这是要点和kotlin操场

期望的结果是函数 testType(superClass: SuperClass<SuperType>) 应该接受类 ChildClass() 而不使用*通配符

One Solution collect form web for “Kotlin泛型超/儿童班”

这是泛型方差 ,阻止你的代码工作。 SuperClass被定义为

 open class SuperClass<T> where T: SuperType { ... } 

而它的类型参数T被声明为不变(它没有outin修饰符)。 因此子类型关系如下:

  • DerivedClass<ChildType> 不是 SuperClass<SuperType>的子类型
  • SuperClass<ChildType> 不是 SuperClass<SuperType>的子类型
  • DerivedClass<SuperType> DerivedClass<SuperType>的子类型。

由于函数参数应该属于参数类型的子类型,并且ChildClass实际上是DerivedClass<ChildType> ,所以不能将ChildClass作为SuperClass<SuperType>传递。

您可以通过将out投影添加到testType的参数类型来解决此问题:

 fun testType(superClass: SuperClass<out SuperType>) 

这基本上意味着这个函数接受SuperClass<T> ,其中TSuperType的子类型。 当然,它增加了对superClass用法的一些限制:因为T可以是SuperType任何子类型,所以将任何东西传递给期望T作为参数的函数并不是类型安全的,这是被禁止的。

另请参阅另一个解释不变泛型行为的原因:( 链接)

  • 注入不能与第二个构造函数一起使用
  • 部署到Android,桌面和浏览器的单个Kotlin + libgdx代码库?
  • 在Recycler视图上复制适配器
  • Kotlin RC NoClassDefFoundError
  • 科特林。 如何检查是否可以通过reflection字段?
  • 错误或功能:Kotlin允许在继承中将“val”更改为“var”
  • 在android kotlin中,使用步进库将自定义单选按钮值传递给多个片段,以便在摘要页面上使用
  • 如何在Kotlin中使用AndroidAnnotation @SharedPref
  • 为什么Kotlin lang只允许项目中的单一主要功能?
  • 用于从子类型推断通用超类型的Kotlin语法
  • kotlin接口能缓存一个值吗?
  • Kotlin language will be the best programming language for Android.