如何解决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(协变)标注,明确类型参数的方差:
- 为
Consumer标注逆变参数
abstract class Consumer<in T> { void consume(T item); }
标注in后,编译器会识别这是一个逆变类型参数,此时Consumer<Object>可以安全地赋值给Consumer<num>,因为Object是num的超类,逆变允许这种向上转换。
- 为
Producer标注协变参数(可选,代码意图更清晰)
abstract class Producer<out T> { T produce(); }
标注out后,Producer<int>可以直接赋值给Producer<num>,符合协变逻辑,让代码的类型关系更直观。
修改后,someFunction(Consumer<num> consumer)就能正常接收Consumer<Object>,同时保留完整的静态类型检查,不会像使用Consumer<dynamic>那样丢失类型约束。
内容的提问来源于stack exchange,提问作者Anakhand
相关产品推荐
相关产品推荐

