Creating an instance of a generic type in DART

2019-03-18 09:56发布

问题:

I was wondering if is possible to create an instance of a generic type in Dart. In other languages like Java you could work around this using reflection, but I'm not sure if this is possible in Dart.

I have this class:

class GenericController <T extends RequestHandler> {

    void processRequest() {
        T t = new T();  // ERROR
    }
}

回答1:

You can use similar code:

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'.");
    }
  }
}


回答2:

I tried mezonis approach with the Activator and it works. But it is an expensive approach as it uses mirrors, which requires you to use "mirrorsUsed" if you don't want to have a 2-4MB js file.

This morning I had the idea to use a generic typedef as generator and thus get rid of reflection:

You define a method type like this: (Add params if necessary)

typedef S ItemCreator<S>();

Then in the class that needs to create the new instances:

class PagedListData<T>{
  ...
  ItemCreator<T> creator;
  PagedListData(ItemCreator<T> this.creator) {

  }

  void performMagic() {
      T item = creator();
      ... 
  }
}

Then you can instanciate the PagedList like this:

PagedListData<UserListItem> users 
         = new PagedListData<UserListItem>(()=> new UserListItem());

You don't loose the Advantage of using generic because at declaration time you need to provide the target class anyway, so defining the creator method doesn't hurt.



回答3:

Sorry but as far as I know, a type parameter cannot be used to name a constructor in an instance creation expression in Dart.



标签: dart