我想知道是否可以在Dart中创建泛型类型的实例.在像Java这样的其他语言中你可以使用反射来解决这个问题,但是我不确定这在Dart中是否可行.
我有这门课:
class GenericController <T extends RequestHandler> {
void processRequest() {
T t = new T(); // ERROR
}
}
Run Code Online (Sandbox Code Playgroud)
Pat*_*sen 43
我尝试了使用Activator的mezonis方法,它的工作原理.但这是一种昂贵的方法,因为它使用镜像,如果你不想拥有2-4MB的js文件,则需要你使用"mirrorsUsed".
今天早上我有了使用泛型typedef作为生成器的想法,从而摆脱了反射:
您可以像这样定义一个方法类型:(如果需要,添加参数)
typedef S ItemCreator<S>();
Run Code Online (Sandbox Code Playgroud)
然后在需要创建新实例的类中:
class PagedListData<T>{
...
ItemCreator<T> creator;
PagedListData(ItemCreator<T> this.creator) {
}
void performMagic() {
T item = creator();
...
}
}
Run Code Online (Sandbox Code Playgroud)
然后你就可以像这样实现PagedList:
PagedListData<UserListItem> users
= new PagedListData<UserListItem>(()=> new UserListItem());
Run Code Online (Sandbox Code Playgroud)
您没有放弃使用泛型的优势,因为在声明时您无论如何都需要提供目标类,因此定义创建者方法不会受到伤害.
All*_* Hu 15
除了以下代码之外,较新版本的 dart 允许您甚至无需传递泛型类型即可实例化,并且代码变得更加简洁:
final myClass = MyClass(SomeOtherClass.new);
Run Code Online (Sandbox Code Playgroud)
感谢@AndriiSyrokomskyi 指出了这一点。
刚刚遇到这个问题,发现虽然T()仍然无法实例化 using ,但可以使用SomeClass.newin更轻松地获取对象的构造函数dart>=2.15。
所以你可以做的是:
class MyClass<T> {
final T Function() creator;
MyClass(this.creator);
T getGenericInstance() {
return creator();
}
}
Run Code Online (Sandbox Code Playgroud)
使用时:
final myClass = MyClass<SomeOtherClass>(SomeOtherClass.new)
Run Code Online (Sandbox Code Playgroud)
没什么不同,但在我看来看起来更干净。
mez*_*oni 12
您可以使用类似的代码:
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'.");
}
}
}
Run Code Online (Sandbox Code Playgroud)
我不知道这对任何人是否仍然有用。但我找到了一个简单的解决方法。在要初始化类型 T 的函数中,传递一个额外的类型参数T Function()。这个函数应该返回一个 T 的实例。现在每当你想创建 T 的对象时,调用这个函数。
class foo<T> {
void foo(T Function() creator) {
final t = creator();
// use t
}
}
Run Code Online (Sandbox Code Playgroud)
PS灵感来自帕特里克的回答
这是我解决这个可悲限制的工作
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();
}
Run Code Online (Sandbox Code Playgroud)