2015-01-22 10 views
6

Sto cercando di scrivere una funzione in una superclasse Dart che prende azioni diverse a seconda di quale sottoclasse è in realtà utilizza. Qualcosa di simile a questo:Accensione tipo di classe a Dart

class Foo { 
    Foo getAnother(Foo foo) { 
    var fooType = //some code here to extract fooType from foo; 
    switch (fooType) { 
     case //something about bar here: 
     return new Bar(); 
     case //something about baz here: 
     return new Baz(); 
    } 
    } 
} 

class Bar extends Foo {} 

class Baz extends Foo {} 

dove l'idea è che ho qualche oggetto e vuole ottenere un nuovo oggetto dello stesso (sotto) categoria.

La questione principale è che tipo dovrebbe essere fooType? Il mio primo pensiero è stato Symbol, che porta a semplici case statement come case #Bar:, ma non so come popolarecon un simbolo. Le uniche opzioni che posso pensare è fare qualcosa di simile Symbol fooType = new Symbol(foo.runtimeType.toString()); ma la mia comprensione è che runtimeType.toString() non funzionerà quando convertito in javascript. Si potrebbe aggirare questo usando Mirrors, ma questo è pensato per essere una libreria leggera, quindi quelli non sono sul tavolo. Object.runtimeType restituisce qualcosa della classe Type, ma non ho idea di come creare istanze di Type potrei usare per le istruzioni case. Forse mi manca qualche altro pezzo della libreria Dart che è più adatto per questo?

+0

comportamento speciale per sottoclassi, a seconda della classe: Questo suona esattamente come quello che le funzioni virtuali sono destinati a risolvere. Che ne dici di avere: 'class Foo {Foo _createNew() => new Foo(); Foo getAnother (Foo foo) => foo._createNew(); } 'e quindi' class Bar estende Foo {_createNew() => new Bar(); } 'e simili per' Baz'? – lrn

risposta

7

È possibile utilizzare la runtimeType in switch:

class Foo { 
    Foo getAnother(Foo foo) { 
    switch (foo.runtimeType) { 
     case Bar: 
     return new Bar(); 
     case Baz: 
     return new Baz(); 
    } 
    return null; 
    } 
} 

Negli case dichiarazioni il nome della classe è utilizzare direttamente (. Aka classe letterale). Questo dà un oggetto Type corrispondente alla classe menzionata. Pertanto, foo.runtimeType può essere confrontato con il tipo specificato.

Si noti che you can not use generics for now in letterali. Pertanto, case List<int>: non è consentito.

+0

Incredibile! Non avevo idea che potessi usare nomi di classe del genere. Devo dire che questo sembra un po 'magico. Potresti spiegare di più su come funziona questo uso (e forse sulla classe Type in generale)? –

+0

Ho aggiornato la mia risposta con ulteriori spiegazioni. –

+0

Questo non funziona con 'List', e' Map', 'Set' e probabilmente altri. –