如何在泛型Dart方法中对泛型类型T强制实现约束?

eh57zj3b  于 2023-11-14  发布在  其他
关注(0)|答案(2)|浏览(140)

我想做的是

我试图创建一个泛型Dart方法,该方法采用泛型类型T,其中T必须实现类IModel。然而,

问题

似乎我不能在类型T上设置implements约束,只能设置extends。例如,<T implements IModel不工作,但<T extends IModel>工作。

代码

IModel.dart作为一个接口:

class IModel {
  IModel();

  factory IModel.fromJson(Map<String, dynamic> json) {
    return IModel();
  }

  Map<String, dynamic> toJson() => {};

  IModel clone() {
    return IModel();
  }
}

字符串
MyModel.dart,一个实现IModel的例子:

import 'dart:core';
import 'package:.../helpers/DateTimeHelper.dart';
import 'package:.../helpers/StringHelper.dart';
import 'package:.../models/IModel.dart';

class MyModel implements IModel {
  String id;
  String name;
  String companyId;
  String projectId;
  String description;
  DateTime created;
  DateTime updated;

  MyModel({this.id, this.name, this.description, this.created, this.updated, this.companyId, this.projectId});

  factory MyModel.fromJson(Map<String, dynamic> json) {
    return MyModel(id: json["id"], name: json["name"], created: DateTime.parse(json["created"]), updated: DateTime.parse(json["updated"]), description: json["description"], companyId: json["companyId"], projectId: json["projectId"]);
  }

  Map<String, dynamic> toJson() => {
        "Id": id,
        "Name": name,
        "Description": description,
        "CompanyId": companyId,
        "ProjectId": projectId,
        "Created": created.toIso8601String(),
        "Updated": updated.toIso8601String()
      };

  MyModel clone() {
    return new MyModel(id: StringHelper.clone(id), companyId: StringHelper.clone(companyId), created: DateTimeHelper.clone(created), updated: DateTimeHelper.clone(updated), name: StringHelper.clone(name), projectId: StringHelper.clone(projectId), description: StringHelper.clone(description));
  }
}


使用泛型方法的ModelHelper.dart:

import 'dart:convert';

import 'package:.../models/IModel.dart';

// 'T implements IModel' not working, but 'T extends IModel' does as constraint.
abstract class ModelHelper {
  static List<T> listFromJson<T implements IModel>(String json) {
    List l = jsonDecode(json)["data"];
    var models = l.map((m) => T.fromJson(m)).toList();
    return models;
  }
}

其他问题/结论

Dart不支持implements约束吗?所有T类都必须扩展IModel吗?

1tuwyuhd

1tuwyuhd1#

问题

似乎我不能在类型T上设置implements约束,只能设置extends。例如<T implements IModel不工作但工作。
这不是问题。你可以安全地使用<T extends IModel>,甚至对于 * 实现 * IModel的类:

abstract class Abstract {}

class Concrete implements Abstract {}

void function<T extends Abstract>(T value) {
  print(value);
}

void main() {
  function<Concrete>(Concrete()); // works
}

字符串

vsmadaxz

vsmadaxz2#

1.没有办法为泛型类型参数指定implements约束,并且这样的约束应该永远不需要。给定:

class Base {}
class Derived1 extends Base {}
class Derived2 implements Base {}

void genericFunction<T extends Base>() {}

字符串
泛型类型约束T extends Base意味着类型参数 * 派生自Base。它不(和 * 不应该 *)要求类型参数使用extends关键字。类型参数使用extends还是implements是该类的实现细节(在本例中为Derived1Derived2),并且不应与泛型(genericFunctionDerived1Derived2的接口都提供与Base相同的接口,而不管它们是使用extends还是implements,这才是最重要的
1.即使泛型类型参数有一个implements约束,它也不会做你想要的事情。你有一个误解,认为Derived implements Base将提供与Base相同的构造函数或static方法。**在Dart中,构造函数和static方法不是类接口的一部分。**它们是不可继承的。例如:

class Base {
  Base.namedConstructor();

  static void staticMethod() {}
}

class Derived implements Base {} // Perfectly legal.

void main() {
  var d = Derived(); // Legal.
  d = Derived.namedConstructor(); // ERROR
  Derived.staticMethod(); // ERROR
}


泛型无法要求类型参数具有特定的构造函数或static方法,因此无法在类型参数上调用构造函数或static方法。通常,您需要传递一个调用所需构造函数或static方法的 callback。特别是对于序列化/重命名JSON,你应该使用一个利用代码生成的现有软件包(如package:json_serializablepackage:built_value),而不是尝试自己实现它。
另请参阅:

相关问题