如何让mutate函数同时接收BoxOf<Food>和BoxOf<Fruit>?
Kotlin泛型类型不匹配问题解决
希望mutate函数能同时接收BoxOf<Food>和BoxOf<Fruit>类型的参数,但调用mutate(BoxOfFruit())时出现类型不匹配错误,提示:Type mismatch: inferred type is BoxOfFruit but BoxOf<Food> was expected。
原代码:
interface Food abstract class BoxOf<C : Food> { val children: MutableList<C> = mutableListOf() } interface Fruit : Food class Apple : Fruit class Lemon : Fruit class BoxOfFood : BoxOf<Food>() class BoxOfFruit : BoxOf<Fruit>() fun mutate(parent: BoxOf<Food>) { parent.children.add(Apple()) parent.children.remove(Lemon()) } fun test() { mutate(BoxOfFood()) mutate(BoxOfFruit()) // Type mismatch: inferred type is BoxOfFruit but BoxOf<Food> was expected }
问题原因
Kotlin中泛型默认是不变的,也就是说BoxOf<Fruit>并不是BoxOf<Food>的子类型——即使Fruit是Food的子类型,泛型容器的类型也不会自动继承。因此无法直接将BoxOfFruit实例传递给参数类型为BoxOf<Food>的函数。
解决方案
将mutate函数改为泛型函数,并通过where约束确保传入的BoxOf<C>的泛型参数C能够兼容Apple和Lemon的类型:
interface Food abstract class BoxOf<C : Food> { val children: MutableList<C> = mutableListOf() } interface Fruit : Food class Apple : Fruit class Lemon : Fruit class BoxOfFood : BoxOf<Food>() class BoxOfFruit : BoxOf<Fruit>() // 修改后的mutate函数 fun <C : Food> mutate(parent: BoxOf<C>) where Apple : C, Lemon : C { parent.children.add(Apple()) parent.children.remove(Lemon()) } fun test() { mutate(BoxOfFood()) // 正常编译,C被推断为Food mutate(BoxOfFruit()) // 正常编译,C被推断为Fruit }
说明
- 泛型参数
C被约束为Food的子类,同时通过where子句确保Apple和Lemon都是C的子类:- 传入
BoxOfFood时,C推断为Food,Apple和Lemon都是Food的子类,满足约束; - 传入
BoxOfFruit时,C推断为Fruit,Apple和Lemon都是Fruit的子类,同样满足约束。
- 传入
- 这种方式既保证了类型安全,又实现了让
mutate函数兼容两种BoxOf类型的需求。
内容的提问来源于stack exchange,提问作者Chpokeridze
相关产品推荐
相关产品推荐

