在DART中创建泛型类型的实例

时间:2014-04-16 14:18:50

标签: dart

我想知道是否可以在Dart中创建泛型类型的实例。在像Java这样的其他语言中你可以使用反射来解决这个问题,但是我不确定这是否可以在Dart中使用。

我有这堂课:

class GenericController <T extends RequestHandler> {

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

7 个答案:

答案 0 :(得分:31)

我尝试了使用Activator的mezonis方法并且它有效。但这是一种昂贵的方法,因为它使用镜像,如果你不想拥有2-4MB的js文件,则需要你使用“mirrorsUsed”。

今天早上我有了使用泛型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());

您没有失去使用泛型的优势,因为在声明时您无论如何都需要提供目标类,因此定义创建者方法不会受到伤害。

答案 1 :(得分:4)

我不知道这是否仍然对任何人有用。但是我发现了一个简单的解决方法。在要初始化类型T的函数中,传递类型T Function()的额外参数。此函数应返回T的实例。现在,无论何时要创建T的对象,都请调用该函数。

class foo<T> {
    void foo(T Function() creator) {
        final t = creator();
        // use t
    }
}

P.S。受Patrick's answer

的启发

答案 2 :(得分:3)

您可以使用类似的代码:

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

答案 3 :(得分:1)

很抱歉,但据我所知,类型参数不能用于在Dart中的实例创建表达式中命名构造函数。

答案 4 :(得分:0)

这是我为这个可悲的限制所做的工作

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();
}

答案 5 :(得分:0)

使用FLutter

typedef S ItemCreator<S>();

mixin SharedExtension<T> {

    T getSPData(ItemCreator<T> creator) async {
        return creator();
    }
}

Abc a = sharedObj.getSPData(()=> Abc());

P.S。受Patrick

的启发

答案 6 :(得分:0)

使用 Patricks 方法,我尝试解决 main.dart 中的代码复杂性。我在我的应用程序中使用 MultiProvider,在使用 Patricks 方法后,我的代码如下所示,

enter image description here

import 'package:app/presentation/home/shop/Cart.dart';
import 'package:app/presentation/home/temple/TempleModel.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:provider/provider.dart';

typedef ItemCreator<T> = T Function();

ChangeNotifierProvider getTempleNotifiers(){
  CreateNotifiers<TempleModel> templeNotifier = new CreateNotifiers<TempleModel>(()=> new TempleModel());
  return templeNotifier.performMagic();
}

ChangeNotifierProvider getCartNotifiers(){
  CreateNotifiers<CartModel> cartNotifier = new CreateNotifiers<CartModel>(()=> new CartModel());
  return cartNotifier.performMagic();
}

class CreateNotifiers<T extends ChangeNotifier> {
  ItemCreator<T> creator;

  CreateNotifiers(ItemCreator<T> this.creator);

  ChangeNotifierProvider performMagic() {
    T item = creator();
    return ChangeNotifierProvider<T>(
      create: (BuildContext context) {
        return item;
      },
    );
  }
}

我有这两个模型 CartTempleModel 来处理我的应用数据。