Creating an instance of a generic type in DART
我想知道是否有可能在Dart中创建泛型类型的实例。 在其他语言(如Java)中,您可以使用反射来解决此问题,但是我不确定在Dart中是否可行。
我有这个课:
1 2 3 4 5 6 | class GenericController <T extends RequestHandler> { void processRequest() { T t = new T(); // ERROR } } |
我尝试了使用Activator的mezonis方法,并且有效。 但这是一种昂贵的方法,因为它使用镜像,如果您不想拥有2-4MB的js文件,则需要使用" mirrorsUsed"。
今天早上,我想到了使用通用的typedef作为生成器,从而摆脱了反射:
您可以定义这样的方法类型:(如有必要,请添加参数)
1 | typedef S ItemCreator(); |
然后在需要创建新实例的类中:
1 2 3 4 5 6 7 8 9 10 11 12 | class PagedListData< T >{ ... ItemCreator< T > creator; PagedListData(ItemCreator< T > this.creator) { } void performMagic() { T item = creator(); ... } } |
然后,您可以像这样实例化PagedList:
1 2 | PagedListData<UserListItem> users = new PagedListData<UserListItem>(()=> new UserListItem()); |
您不会失去使用泛型的优势,因为在声明时无论如何都需要提供目标类,因此定义creator方法不会受到损害。
您可以使用类似的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | import"dart:mirrors"; void main() { var controller = new GenericController<Foo>(); controller.processRequest(); } class GenericController<T extends RequestHandler> { void processRequest() { //T t = new T(); T t = Activator.createInstance(T); t.tellAboutHimself(); } } class Foo extends RequestHandler { void tellAboutHimself() { print("Hello, I am 'Foo'"); } } abstract class RequestHandler { void tellAboutHimself(); } class Activator { static createInstance(Type type, [Symbol constructor, List arguments, Map<Symbol, dynamic> namedArguments]) { if (type == null) { throw new ArgumentError("type: $type"); } if (constructor == null) { constructor = const Symbol(""); } if (arguments == null) { arguments = const []; } var typeMirror = reflectType(type); if (typeMirror is ClassMirror) { return typeMirror.newInstance(constructor, arguments, namedArguments).reflectee; } else { throw new ArgumentError("Cannot create the instance of the type '$type'."); } } } |
抱歉,据我所知,不能在Dart中的实例创建表达式中使用类型参数来命名构造函数。
这是我为这个可悲的局限性所做的工作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | class RequestHandler { static final _constructors = { RequestHandler: () => RequestHandler(), RequestHandler2: () => RequestHandler2(), }; static RequestHandler create(Type type) { return _constructors[type](); } } class RequestHandler2 extends RequestHandler {} class GenericController<T extends RequestHandler> { void processRequest() { //T t = new T(); // ERROR T t = RequestHandler.create(T); } } test() { final controller = GenericController<RequestHandler2>(); controller.processRequest(); } |