Создание экземпляра родового типа в DART
Мне было интересно, возможно ли создать экземпляр родового типа в Dart. На других языках, таких как Java, вы можете обойти это с помощью отражения, но я не уверен, возможно ли это в Dart.
У меня есть этот класс:
class GenericController <T extends RequestHandler> {
void processRequest() {
T t = new T(); // ERROR
}
}
Ответы
Ответ 1
Вы можете использовать похожий код:
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
Я попытался использовать mezonis с Activator, и он работает. Но это дорогостоящий подход, поскольку он использует зеркала, что требует от вас использования "mirrorUsed", если вы не хотите иметь файл js 2-4MB.
Сегодня утром у меня возникла идея использовать общий генератор typedef в качестве генератора и, таким образом, избавиться от отражения:
Вы определяете тип метода следующим образом: (При необходимости добавьте параметры)
typedef S ItemCreator<S>();
Затем в классе, который должен создать новые экземпляры:
class PagedListData<T>{
...
ItemCreator<T> creator;
PagedListData(ItemCreator<T> this.creator) {
}
void performMagic() {
T item = creator();
...
}
}
Затем вы можете инициировать PagedList следующим образом:
PagedListData<UserListItem> users
= new PagedListData<UserListItem>(()=> new UserListItem());
Вы не теряете преимущества использования общего, потому что во время объявления вам нужно предоставить целевой класс, так что определение метода создателя не повредит.
Ответ 3
Извините, но насколько я знаю, параметр типа нельзя использовать для обозначения конструктора в выражении создания экземпляра в Dart.
Ответ 4
Вот моя работа для этого печального ограничения
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();
}