2017-04-17 69 views
1

尝试使用泛型类,但得到了下面的问题,那就是:科特林泛型超/子类

类型不匹配:推断类型是ChildClassSuperClass<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 
    } 
} 

这里是the gistthe kotlin playground

所需结果LT是功能testType(superClass: SuperClass<SuperType>)应该接受类ChildClass()不使用通配符*

+0

请在问题本身的代码。 – nhaarman

回答

1

这是generics variance,防止您的代码工作。 SuperClass被定义为

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

,其类型参数T被声明为不变的(它没有outin改性剂)。因此,分型的关系如下:

  • DerivedClass<ChildType>SuperClass<SuperType>
  • SuperClass<ChildType>亚型是SuperClass<SuperType>
  • DerivedClass<SuperType>亚型是SuperClass<SuperType>亚型。

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

您可以通过添加out projection参数类型的testType解决这个问题:

fun testType(superClass: SuperClass<out SuperType>) 

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

另外,看到另一种答案,解释为不变仿制药的行为的原因:(link)