【问题标题】:Dart - Problem replicating sealed classes like kotlinDart - 复制像 kotlin 这样的密封类时出现问题
【发布时间】:2021-04-30 10:32:25
【问题描述】:

我在编写的起始示例中遇到此错误

type 'Error<dynamic>' is not a subtype of type 'FutureOr<Success<List<TaskEntity>>>'

我创建了一个这样的通用 Result 类:

enum DataStatus { local, remote, error }

enum ErrorStatus { unknown, backend_error, timeout }

@sealed
abstract class Result<T> {}

class Success<T> extends Result<T> {
  final T data;
  final DataStatus dataStatus;
  final String message;

  Success({this.data, this.dataStatus, this.message});
}

class Error extends Result {
  final Exception exception;
  final ErrorStatus errorStatus;
  final String message;

  Error({this.exception, this.errorStatus, this.message});
}

在我的存储库中,我有这个方法:

Future<Result<List<TaskEntity>>> getTasks() {
    return remoteDataSource
      .getTasks()
        .then((value) => Success(
            data: value.map((e) => e.toTaskEntity()).toList(),
            dataStatus: DataStatus.remote))
        .catchError((Object obj) {
      switch (obj.runtimeType) {
        case DioError:
          final dioErrorResponse = (obj as DioError).response;
          return Error(
              exception: Exception(dioErrorResponse.statusMessage),
              errorStatus: ErrorStatus.backend_error,
              message: dioErrorResponse.statusMessage);
          break;
        default:
      }
    });

我的方法是使用这个类返回响应,如果有错误返回错误。

现在我被阻止了,因为我收到了这个错误

type 'Error<dynamic>' is not a subtype of type 'FutureOr<Success<List<TaskEntity>>>'

我也尝试使用冻结的库,但没有成功。

 part 'result.freezed.dart';

 @freezed
 abstract class Result<T> with _$Result<T> {
   const factory Result.success({T data, DataStatus dataStatus, String message}) = Success<T>;
   const factory Result.error({Exception exception, ErrorStatus errorStatus,  String message}) = Error;
 }

【问题讨论】:

    标签: flutter dart


    【解决方案1】:

    您的问题是您从未直接或隐含地为您的错误类指定T。所以它是一个Error&lt;dynamic&gt;。但是Error&lt;dynamic&gt; 不会扩展Result&lt;List&lt;TaskEntity&gt;&gt;Error&lt;List&lt;TaskEntity&gt;&gt; 会。因此,您需要确保您的 Error 类也获得 T 的类型。

    说实话,整个 .then .catch 事情对我来说太复杂了。我会使用 asyncawait 和普通的 try/catch 块。但如果你想保持原样,至少要确保你这样做:

    return Error<List<TaskEntity>>(
    

    所以你的 Error&lt;&gt; 类在语法上是正确的类型。


    作为一个例子,我通过使用asyncawait 使其变得更容易:

    Future<Result<List<TaskEntity>>> getTasks() async {
       try {
         final results = await remoteDataSource.getTasks();
         final tasks = results.map((e) => e.toTaskEntity()).toList()
    
         return Success<List<TaskEntity>>(data: tasks, dataStatus: DataStatus.remote);
       } catch (e) {
           if (e is DioError) {
               return Error<List<TaskEntity>>(
                 exception: Exception(e.response.statusMessage),
                 errorStatus: ErrorStatus.backend_error,
                 message: e.response.statusMessage);
           } else {
             // you are missing a case here? what do you want to return here?
           }
       }
    }
    

    对我来说,这更容易阅读,以至于很明显你错过了一个案例。那里需要有return 声明。

    【讨论】:

    • 感谢您的回答,但没有奏效。我已经实现了结果:``` class Error extends Result { ``` 我返回了:``` return Error>( exception: Exception(dioErrorResponse.statusMessage), errorStatus :ErrorStatus.backend_error,消息:dioErrorResponse.statusMessage); ```但现在错误是:```未处理的异常:类型'Error>'不是'FutureOr>>'类型的子类型```
    • 嗯,那是因为您使用了.then .catch 样式。将两者都转换为Result&lt;List&lt;TaskEntity&gt;&gt;,它应该可以工作,或者使用asyncawait,这样编译器就足够聪明,可以自己解决。
    猜你喜欢
    • 2023-02-20
    • 1970-01-01
    • 2019-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多