You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 13:13:30