Flutter错误:参数类型NumberTrivia无法赋值给NumberTriviaModel
跟随YouTube Flutter应用开发系列教程学习时,视频运行正常,但本地IDE抛出类型不匹配错误:
Flutter error: The argument type 'NumberTrivia' can't be assigned to the parameter type 'NumberTriviaModel'
错误定位在number_trivia_repository_impl.dart中的localDataSource.cacheNumberTrivia(remoteTrivia);代码行。
相关代码文件如下:
1. number_trivia.dart
import 'package:equatable/equatable.dart'; class NumberTrivia extends Equatable { final String text; final int number; NumberTrivia({ required this.text, required this.number, }) : super(); }
2. number_trivia_model.dart
import '../../domain/entities/number_trivia.dart'; class NumberTriviaModel extends NumberTrivia { NumberTriviaModel({ required String text, required int number, }) : super(text: text, number: number); factory NumberTriviaModel.fromJson(Map<String, dynamic> json) { return NumberTriviaModel( text: json["text"], number: (json["number"] as num).toInt(), ); } Map<String, dynamic> toJson() => { "text": text, "number": number, }; }
3. number_trivia_repository_impl.dart(错误所在文件)
import 'package:dartz/dartz.dart'; import 'package:meta/meta.dart'; import '../../../../core/error/exception.dart'; import '../../../../core/error/failures.dart'; import '../../../../core/platform/network_info.dart'; import '../../domain/entities/number_trivia.dart'; import '../../domain/repositories/number_trivia_repository.dart'; import '../datasources/number_trivia_local_data_source.dart'; import '../datasources/number_trivia_remote_data_source.dart'; typedef Future<NumberTrivia> _ConcreteOrRandomChooser(); class NumberTriviaRepositoryImpl implements NumberTriviaRepository { final NumberTriviaRemoteDataSource remoteDataSource; final NumberTriviaLocalDataSource localDataSource; final NetworkInfo networkInfo; NumberTriviaRepositoryImpl( @required this.remoteDataSource, @required this.localDataSource, @required this.networkInfo, ); @override Future<Either<Failure, NumberTrivia>> getConcreteNumberTrivia( int number, ) async { return await _getTrivia(() { return remoteDataSource.getConreteNumberTrivia(number); }); } @override Future<Either<Failure, NumberTrivia>> getRandomNumberTrivia() async { return await _getTrivia(() { return remoteDataSource.getRandomNumberTrivia(); }); } Future<Either<Failure, NumberTrivia>> _getTrivia( _ConcreteOrRandomChooser getConcreteOrRandom, ) async { if (await networkInfo.isConnected) { try { final remoteTrivia = await getConcreteOrRandom(); localDataSource.cacheNumberTrivia(remoteTrivia); // 错误位置 return Right(remoteTrivia); } on ServerException { return Left(ServerFailure()); } } else { try { final localTrivia = await localDataSource.getLastNumberTrivia(); return Right(localTrivia); } on CacheException { return Left(CacheFailure()); } } } }
错误核心是父类与子类的类型兼容性问题:NumberTrivia是父类,NumberTriviaModel是它的子类,Dart不允许直接将父类实例传递给要求子类类型的参数。
以下是三种可行修复方案,按推荐优先级排序:
方案一:修改本地数据源的方法参数类型(推荐)
调整NumberTriviaLocalDataSource中cacheNumberTrivia方法的参数类型,从NumberTriviaModel改为NumberTrivia。这样该方法可以接收任何NumberTrivia的子类实例,符合依赖倒置原则,让Repository层依赖抽象而非具体实现,代码扩展性更强。
方案二:确保远程数据源返回子类实例
检查NumberTriviaRemoteDataSource的两个方法(getConreteNumberTrivia和getRandomNumberTrivia)的返回类型,将其从Future<NumberTrivia>改为Future<NumberTriviaModel>。同时更新_ConcreteOrRandomChooser的定义:
typedef Future<NumberTriviaModel> _ConcreteOrRandomChooser();
此时remoteTrivia的类型就是NumberTriviaModel,可以直接传入cacheNumberTrivia方法。
方案三:强制类型转换(应急用,不推荐)
如果前两种方案无法实施,可以在调用cacheNumberTrivia时将父类实例强制转换为子类,但必须确保remoteTrivia实际是NumberTriviaModel实例,否则会触发运行时异常:
localDataSource.cacheNumberTrivia(remoteTrivia as NumberTriviaModel);
内容的提问来源于stack exchange,提问作者Mou Rani Biswas

