Dart继承类时列表赋值报错:MyEntity无法转为MyModel
问题:Clean Architecture中Entities与Models列表操作的类型不兼容错误
在遵循Clean Architecture规范使用Entities和Models时,遍历Entities列表修改元素时出现错误:
Uncaught Error: TypeError: Instance of 'MyEntity': type 'MyEntity' is not a subtype of type 'MyModel'
复现代码如下:
class MyEntity { final String id; const MyEntity({ required this.id, }); MyEntity copyWith({ String? id, }) { return MyEntity( id: id ?? this.id, ); } } class MyModel extends MyEntity { const MyModel({ required super.id, }); factory MyModel.fromJson(Map<String, dynamic> map) { return MyModel( id: map['id'] ?? "", ); } } void main() { final List<MyModel> modelsList = [ MyModel.fromJson({'id': '0'}), MyModel.fromJson({'id': '1'}), MyModel.fromJson({'id': '2'}), ]; final List<MyEntity> entitiesList = modelsList; for (var i = 0; i < entitiesList.length; i++) { entitiesList[i] = entitiesList[i].copyWith(id: '99'); } }
错误原因
Dart中列表的类型声明支持协变,但底层实际存储的列表类型不会改变:
final List<MyEntity> entitiesList = modelsList;这行代码只是给原List<MyModel>对象套了一个List<MyEntity>的类型声明,本质上entitiesList仍然指向原来的List<MyModel>实例。MyEntity的copyWith方法返回的是MyEntity类型实例,而原列表只能存储MyModel类型对象,因此赋值时会触发类型不兼容错误。
而List<MyEntity>.from(modelsList)是创建了一个全新的List<MyEntity>实例,这个列表可以存储MyEntity及其所有子类对象,因此赋值操作不会报错。
解决方案
方案1:创建新的List<MyEntity>实例
使用List.from或cast方法生成新列表,切断与原List<MyModel>的关联:
final List<MyEntity> entitiesList = List<MyEntity>.from(modelsList); // 或者使用cast final List<MyEntity> entitiesList = modelsList.cast<MyEntity>();
方案2:重写子类的copyWith方法
让MyModel的copyWith返回自身类型,这样即使操作原List<MyModel>,赋值的也是兼容的MyModel实例:
class MyModel extends MyEntity { const MyModel({ required super.id, }); factory MyModel.fromJson(Map<String, dynamic> map) { return MyModel( id: map['id'] ?? "", ); } @override MyModel copyWith({String? id}) { return MyModel( id: id ?? this.id, ); } }
内容的提问来源于stack exchange,提问作者TheEL
相关产品推荐
相关产品推荐

