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() 而不使用*通配符

这是泛型方差 ,阻止你的代码工作。 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作为参数的函数并不是类型安全的,这是被禁止的。

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