You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 01:52:38