如何在实现特定Mixin/接口的Freezed联合类上使用copyWith方法
解决方案
Freezed生成的联合类型父类copyWith方法,只会包含所有工厂构造的公共参数,population是City子类独有字段(Person无该字段),因此父类Example的copyWith不会暴露这个参数,直接调用自然无法生效,按以下两步处理即可:
- 第一步:用
is关键字做类型检查,判断实例是否实现GeographicArea接口、属于对应子类 - 第二步:通过Dart的类型提升特性,调用具体子类的copyWith修改专属字段
基础写法(仅当前City实现接口的场景)
直接判断实例是否为City类型,类型检查通过后Dart会自动完成类型提升,无需手动强转即可调用City专属的copyWith参数:
void main() { Example example = Example.city('Guangzhou', 18800000); // 类型判断 if (example is City) { // 此时example自动被识别为City类型,可正常传入population参数 example = example.copyWith(population: 20000000); } // 验证结果 if (example is GeographicArea) { print('城市名称: ${example.name}, 修改后人口: ${example.population}'); // 输出:城市名称: Guangzhou, 修改后人口: 20000000 } }
如果当前实例是Example.person生成的Person类型,类型判断不会通过,不会执行修改逻辑,不会抛出运行时错误。
扩展写法(后续可能新增其他实现GeographicArea的子类场景)
如果后续你可能给Example新增其他实现GeographicArea接口的工厂,可以先用接口做判断,再用模式匹配对应子类处理,避免漏改:
Example updatePopulationIfNeeded(Example example, int newPopulation) { // 先判断是否实现了目标接口 if (example is! GeographicArea) return example; // 匹配具体子类调用对应copyWith return switch (example) { City() => example.copyWith(population: newPopulation), // 后续新增其他实现GeographicArea的Example子类,在这里加对应分支即可 // 比如新增District类的话: District() => example.copyWith(population: newPopulation), _ => example, }; }
注意:不要尝试给父类Example的copyWith强行加子类参数,Freezed的代码生成逻辑不会合并子类独有的字段到父类copyWith签名中,必须在具体子类的类型上下文下调用copyWith才能访问专属参数。
内容的提问来源于stack exchange,提问作者Christian
相关产品推荐
相关产品推荐

