Flutter Freezed联合类型子类型字段copyWith简洁使用方案问询
解决方案
针对Freezed联合类同名字段类型不同时copyWith调用繁琐的问题,有3种可落地的方案:
1. 公共字段下沉到抽象父类
如果所有VeganItem子类型都包含id、images这类公共字段,直接将字段定义到抽象父类VeganItemAbstraction中:
abstract class VeganItemAbstraction { int? get id; List<ImagePickerImage>? get images; // 其余所有子类型共有的字段都在此处声明 }
Freezed会自动识别全量子类型共有的字段,无论veganItem声明为超类型还是子类型,都可以直接使用链式copyWith语法:
mvipVm.entity = mvipVm.entity!.copyWith.veganItem!(id: null, images: null);
该方案是类型安全最高、改造代价最小的最优解。
2. 扩展方法封装重复逻辑
如果无法调整抽象父类的定义,可以针对VeganItemEstablishment写一个扩展方法,把重复的map逻辑收拢:
extension VeganItemEstablishmentCopyWith on VeganItemEstablishment { VeganItemEstablishment copyWithVeganItem({ int? id, List<ImagePickerImage>? images, }) { return map( groceryItemEstablishment: (v) => v.copyWith(veganItem: v.veganItem?.copyWith(id: id, images: images)), menuItemEstablishment: (v) => v.copyWith(veganItem: v.veganItem?.copyWith(id: id, images: images)), restaurantItemEstablishment: (v) => v.copyWith(veganItem: v.veganItem?.copyWith(id: id, images: images)), eventItemEstablishment: (v) => v.copyWith(veganItem: v.veganItem?.copyWith(id: id, images: images)), groceryStoreItemEstablishment: (v) => v.copyWith(veganItem: v.veganItem?.copyWith(id: id, images: images)), ); } }
封装后调用侧只需要一行代码即可完成赋值:
mvipVm.entity = mvipVm.entity!.copyWithVeganItem(id: null, images: null);
冗余逻辑只需要写一次,后续维护只需要调整扩展方法即可。
3. 保留超类型声明按需强转
也就是你目前在用的方案,将veganItem统一声明为超类型VeganItem,仅在需要访问子类型独有字段时,通过as强转或者when/map分支处理类型。该方案不需要额外编写辅助代码,可维护性最高,适合子类型独有逻辑不多的场景。
Freezed的copyWith设计本身就是为了保证类型安全,只有所有子类型的字段名+字段类型完全一致时,才会生成顶层的链式copyWith调用,避免编译期隐式类型转换带来的运行时异常。
内容的提问来源于stack exchange,提问作者BeniaminoBaggins
相关产品推荐
相关产品推荐

