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

如何解决Dart中缺乏不变/逆变类型参数的问题?

Dart中实现逆变/不变类型参数的解决方案

Dart出于设计原因不支持显式指定不变或逆变类型参数,遇到需要这类参数的场景时,我们可以通过泛型方差标注来解决问题。

先看示例中的抽象类:

abstract class Producer<T> {
  T produce();
}

abstract class Consumer<T> {
  void consume(T item);
}

Producer的类型参数适合协变(返回值场景天然支持协变),而Consumer的类型参数应该是逆变——比如能接收任意Object的消费者,必然能处理num类型的输入,但Dart默认将所有泛型参数设为协变,导致Consumer<num>无法接收Consumer<Object>这种符合逆变逻辑的类型。

比如定义如下函数:

void someFunction(Consumer<num> consumer);

它只会接受Consumer<num>、Consumer<int>这类协变子类,而我们期望的Consumer<Object>会被编译器拒绝,这不符合实际需求。

正确解决方案:泛型方差标注

Dart支持在类的泛型参数前添加in(逆变)和out(协变)标注,明确类型参数的方差:

  1. 为Consumer标注逆变参数
abstract class Consumer<in T> {
  void consume(T item);
}

标注in后,编译器会识别这是一个逆变类型参数,此时Consumer<Object>可以安全地赋值给Consumer<num>,因为Object是num的超类,逆变允许这种向上转换。

  1. 为Producer标注协变参数(可选,代码意图更清晰)
abstract class Producer<out T> {
  T produce();
}

标注out后,Producer<int>可以直接赋值给Producer<num>,符合协变逻辑,让代码的类型关系更直观。

修改后,someFunction(Consumer<num> consumer)就能正常接收Consumer<Object>,同时保留完整的静态类型检查,不会像使用Consumer<dynamic>那样丢失类型约束。

内容的提问来源于stack exchange,提问作者Anakhand

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 00:56:08