2014-04-16 6 views
5

Mi chiedevo se è possibile creare un'istanza di un tipo generico in Dart. In altre lingue come Java è possibile aggirare questo problema usando il reflection, ma non sono sicuro che ciò sia possibile in Dart.Creazione di un'istanza di un tipo generico in DART

ho questa classe:

class GenericController <T extends RequestHandler> { 

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

I parametri di tipo in Dart implementano l'interfaccia 'Type'. L'interfaccia 'Tipo' non dichiara alcun membro. Ciò significa che l'interfaccia 'Type' viene utilizzata solo come chiave di identità dei tipi di runtime. Le procedure di riflessione integrate in Dart SDK ma non fanno parte del core Dart. Ciò significa che se vuoi introspettare il tuo programma dovresti usare la reflection library. Il bridge tra il tuo programma (in fase di esecuzione) e la reflection library è l'interfaccia 'Type'. Richiedete (riflettete) le informazioni richieste sulle classi usando questa interfaccia. – mezoni

+0

Vedi anche https://github.com/dart-lang/sdk/issues/12921 –

risposta

4

È possibile utilizzare il codice simile:

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

Grazie a mezoni, che funziona come previsto – shuriquen

0

Siamo spiacenti ma per quanto ne so, un parametro di tipo non può essere utilizzato per chiamare un costruttore in un'espressione creazione dell'istanza di Dart.

4

ho cercato mezonis approccio con l'attivatore e funziona. Ma è un approccio costoso in quanto utilizza i mirror, che richiede l'utilizzo di "mirrorsUsed" se non si desidera avere un file js 2-4 MB.

Questa mattina ho avuto l'idea di utilizzare un typedef generico come generatore e quindi sbarazzarsi di riflessione:

si definisce un tipo metodo come questo: (Aggiungi params se necessario)

typedef S ItemCreator<S>(); 

Poi nella classe che ha bisogno di creare le nuove istanze:

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

    } 

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

Quindi è possibile instanciate il PagedList in questo modo:

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

Non perde il vantaggio di utilizzare generica in quanto al momento della dichiarazione è necessario fornire la classe di destinazione in ogni caso, in modo da definire il metodo creatore non fa male.