如何创建返回泛型参数化类的方法?解决Bird<Food>类型不匹配问题
解决Kotlin泛型类型不匹配问题:Bird无法转为Bird
这个问题其实是Kotlin泛型不变性导致的——虽然Fish是Food的子类,但默认情况下Bird<Fish>和Bird<Food>之间并没有继承关系,所以编译器会抛出类型不匹配的错误。下面给你两种常用的解决办法:
方案一:让Bird类支持协变(推荐,若可修改Bird类)
如果有权修改Bird抽象类的定义,可以给泛型参数T加上out关键字,开启协变。协变的作用是:当T只作为类的输出(比如返回值、只读属性)时,允许Bird<SubType>被当作Bird<SuperType>使用(这里SubType是SuperType的子类)。
修改后的代码示例:
abstract class Food class Fish : Food() // 给泛型T添加out关键字,支持协变 abstract class Bird<out T : Food> class Falcon : Bird<Fish>() const val SOME_CONSTANT = 1 fun getBird(type: Int): Bird<Food> { if (type == SOME_CONSTANT) { return Falcon() // 现在编译通过,因为Bird<Fish>是Bird<Food>的子类型 } else { // 示例:返回其他鸟类实现,比如以Seed为食物的麻雀 // return Sparrow() throw IllegalArgumentException("Unknown bird type") } }
注意:如果Bird类中有接收T作为参数的方法(比如fun eat(food: T)),就不能使用协变了——因为out要求T只能出现在输出位置,不能作为输入参数的类型。
方案二:使用通配符(无需修改Bird类)
如果不能修改Bird类的定义,可以在方法的返回类型中使用out通配符,把返回类型改为Bird<out Food>。这样编译器会允许返回任何Bird<SubFood>(SubFood是Food的子类)。
代码示例:
abstract class Food class Fish : Food() // 保持原Bird类定义不变 abstract class Bird<T : Food> class Falcon : Bird<Fish>() const val SOME_CONSTANT = 1 fun getBird(type: Int): Bird<out Food> { // 使用out通配符 if (type == SOME_CONSTANT) { return Falcon() // 编译通过 } else { throw IllegalArgumentException("Unknown bird type") } }
这种方式的局限性是:调用getBird()的代码只能读取Bird中返回T的属性/方法,不能调用接收T作为参数的方法(因为编译器无法确定具体的T类型)。
内容的提问来源于stack exchange,提问作者ono
相关产品推荐
相关产品推荐

