Dart中Map<String,A>与Map<String,B>参数类型兼容性问题咨询
关于Map<String, A>和Map<String, B>的兼容性
Dart的泛型默认是协变规则,只要B是A的子类,Map<String, B>就属于Map<String, A>的子类型,静态类型检查会直接判定为合法,这是Dart类型系统的刻意设计,不是运行时副作用,泛型参数在运行时也是会真实校验的。
不过要注意这个协变的限制:你只能从这个Map里读值,不能写入不符合原Map泛型约束的值。比如你在goofy函数里执行map["b2"] = A(),运行时就会直接抛出类型错误,因为你传入的实际是Map<String, B>,只能存储B类型的实例。
三个函数的写法优劣
goofy的写法是最推荐的:有完整的静态类型检查,不需要强制类型转换,只要你不在函数内修改Map写入不符合约束的值,运行时完全不会有问题。croc和frape用了dynamic参数,丢失了静态类型校验的能力,比如你不小心传入一个List实例作为参数,编译不会报错,运行时才会抛出异常,非常不推荐。
支持传入值为A或B类型的Map的推荐写法
如果你只需要从Map读取数据,不需要写入,直接用Map<String, A>作为参数类型即可,Map<String, B>可以直接传入,不需要额外处理。
如果你需要在函数内往Map写入数据,建议直接使用Map<String, A>类型的实例作为入参,这个类型的Map本身就支持存储A和所有A的子类(包括B)的实例,不需要做任何类型转换。
关于无泛型普通Map的问题
语法上可行,但极其不推荐。无泛型的Map相当于Map<dynamic, dynamic>,所有键值的类型都不会做静态检查,你读取值的时候还需要手动做类型转换,大大提升了运行时出问题的概率,完全浪费了Dart强类型系统的优势。
内容的提问来源于stack exchange,提问作者The Tosters
相关产品推荐
相关产品推荐

