Dart:函数的类型安全性,该函数将具有变化的返回值的函数作为参数

时间:2018-10-30 02:52:09

标签: dart parametric-polymorphism

我正在尝试创建一个Dart函数,该函数本质上是使用一些样板错误处理代码包装其他函数的,否则将返回原始函数返回的值。一个关键要求是它应该接受具有多个不同返回类型的函数,同时避免在多个不同函数之间重复通用错误处理逻辑。我发现一种方法似乎可以通过使用动态类型来工作,除了编译器无法检测类型不匹配之外,因此它们只能在运行时捕获。

是否有更好的方法来实现我的目标,特别是在编译时捕获类型不匹配的方法?

下面是我的代码的简化示例,其中的函数可以很好地编译,但是在运行时getAString将引发错误Dart Error: Unhandled exception: type 'List<String>' is not a subtype of type 'String'

/// API函数调用的签名     typedef APIFunctionCall =动态Function();

dynamic doWithErrorHandling(APIFunctionCall fn, {retries: 2}) async {
  for (int attempts = 0; attempts < retries + 1; attempts++) {
    try {
      return await fn();
    }
    on Exception catch (e) {
      print(
          "This is just an example; actual function does a bunch of more specific error handling.");
    }
  }
}

Future<String> getAString() async {
  // Want a function that can support multiple return types but detect type errors
  String doesReturnAString =  await doWithErrorHandling(() async => 'hello world');  // This runs fine
  String doesntReturnAString = await doWithErrorHandling(() async => <String>['hello', 'world']);  // This throws an Error
  return doesntReturnAString;
}

1 个答案:

答案 0 :(得分:3)

您可以使用类型参数抽象返回类型:

Future<T> doWithErrorHandling<T>(Future<T> fn(), {int retries = 2}) async {
  do {
    try {
      return await fn();
    } catch (e) {
      // record error.
    }
    retries--;
  } while (retries >= 0);
  return null;  // or whatever.
} 

这样,您可以使用任何函数进行调用。在大多数情况下,可以从参数函数的静态类型或周围环境期望的类型中推断出类型参数,但是如果没有,则可以自己编写。

Future<String> getAString() async {
  String doesReturnAString =  await doWithErrorHandling(() async => 'hello world');  
  // The next line has a compile-time type error!
  String doesntReturnAString = await doWithErrorHandling(() async => <String>['hello', 'world']);
  return doesntReturnAString;
}

(作为不相关的提示,您永远不要抓住Exception。Dart 错误不实现Exception,它们实现ErrorException是由用户用来捕获和处理的某些抛出对象使用的无意义的标记接口,但是在这种情况下,您应该捕获特定的异常,例如on FormatException,而不是普通的Exception。因此,一般规则:切勿写on Exception)。