如何从Dart / Flutter中的泛型函数调用命名构造函数

Ame*_*een 6 generics constructor dart flutter

我希望能够从通用函数内部构造一个对象。我尝试了以下方法:

abstract class Interface
{
  Interface.func(int x);
}
class Test implements Interface
{
  Test.func(int x){}
}
T make<T extends Interface>(int x)
{
  // the next line doesn't work
  return T.func(x);
}
Run Code Online (Sandbox Code Playgroud)

但是,这不起作用。而且我收到以下错误消息:The method 'func' isn't defined for the class 'Type'

注意:我不能使用镜子,因为我正在使用带有飞镖的飞镖。

und*_*ock 11

G\xc3\xbcnter Z\xc3\xb6chbauer 的出色答案和使用 Dart 2.15 中新的构造函数撕除功能的一个变体可能是向泛型函数添加一个额外的参数以提供构造函数(Test.new如果需要,可用于默认构造函数) 。

\n
T make2<T extends Interface>(int x, T Function(int) constructor)\n{\n  return constructor(x);\n}\n\nmake2<Test>(5, Test.func);\n\n// Default constructor\nmake2<Test>(5, Test.new);\n
Run Code Online (Sandbox Code Playgroud)\n

参数T Function(int) constructor是一个 Function ,它接受一个int参数并返回 Type T

\n

您也可以在没有构造函数撕裂的情况下完成此操作,但是(至少对我来说)这有点难以解析。

\n
make2<Test>(5, (int x) => Test.func(x));\n
Run Code Online (Sandbox Code Playgroud)\n

这还有一个有用的属性,如果开发人员在不更改参数的情况下复制并粘贴函数,则应该通过静态分析向他们发出警报(因为AnotherTest.func不返回Test),而不是仅在运行时将工厂列表与工厂列表进行比较时找出类型。

\n
// ERROR: The argument type 'AnotherTest Function(int)' can't be \n// assigned to the parameter type 'Test Function(int)'\nmake2<Test>(5, AnotherTest.func);\n
Run Code Online (Sandbox Code Playgroud)\n


rai*_*tic 10

我还没有看到任何好的(完整/具体/非深奥!)解决方法示例,所以这是我的:

使用方法如下:

主程序.dart

void main() {
  final user = Model.fromJson<User>({
    "id": 1,
    "username": "bobuser",
    "name": "Bob",
    "email": "bob@example.com",
  });
  print(user.runtimeType);
  print(user is User); // Unnecessary type check; the result is always 'true'.
  print(user.toJson());
}
Run Code Online (Sandbox Code Playgroud)
dart lib/main.dart
Run Code Online (Sandbox Code Playgroud)
User
true
{id: 1, username: bobuser, name: Bob, email: bob@example.com}
Run Code Online (Sandbox Code Playgroud)

模型.dart

User
true
{id: 1, username: bobuser, name: Bob, email: bob@example.com}
Run Code Online (Sandbox Code Playgroud)

  • 这正是我提出问题的用例。我相信每个使用 dart 的人都会有这个用例,因为无论他们是编写移动应用程序还是 Web 应用程序,都必须为来自服务器或数据库的数据编写反序列化器。 (2认同)

Gün*_*uer 6

Dart不支持从泛型类型参数实例化。您要使用命名构造函数还是默认构造函数T()都没关系(这也不起作用)。

可能有一种方法可以在服务器上执行此操作,该服务器上可以使用dart:mirrors(反射)(尚未尝试过),但在Flutter或浏览器中却没有。

您需要维护类型到工厂功能的映射

void main() async {
  final double abc = 1.4;
  int x = abc.toInt();
  print(int.tryParse(abc.toString().split('.')[1]));
//  int y = abc - x;
  final t = make<Test>(5);
  print(t);
}

abstract class Interface {
  Interface.func(int x);
}

class Test implements Interface {
  Test.func(int x) {}
}

/// Add factory functions for every Type and every constructor you want to make available to `make`
final factories = <Type, Function>{Test: (int x) => Test.func(x)};

T make<T extends Interface>(int x) {
  return factories[T](x);
}
Run Code Online (Sandbox Code Playgroud)

  • 有趣的是,Flutter“从互联网获取数据”教程显示了“fromJson”方法,然后在泛型类型上调用此方法的失败尝试中出现了“各种”线程。我不明白为什么 `&lt;T Implements X&gt;` 不能保证 T 有一个由 `X` 声明的 `fromJson` (`T.fromJson(...)`)。 (14认同)
  • 遗憾的是这是不可能的,因为那会非常有用。 (9认同)
  • 这主要是关于工作量和增加的复杂性是否值得。Dart 团队正在努力使 Dart 变得更好,这是经常出现的问题。我猜他们最终会解决这个问题,但目前似乎正在开发其他具有更好成本/价值比的功能。 (3认同)