Come eseguire il controllo del tipo in runtime in Dart?


103

La specifica Dart afferma:

Le informazioni sul tipo reificato riflettono i tipi di oggetti in fase di esecuzione e possono sempre essere interrogate da costrutti dinamici di controllo del tipo (gli analoghi di instanceOf, cast, typecase ecc. In altre lingue).

Sembra fantastico, ma non c'è un instanceofoperatore simile. Quindi come eseguiamo il controllo del tipo in runtime in Dart? È possibile?

Risposte:


147

L'operatore instanceof è chiamato isin Dart. Le specifiche non sono esattamente amichevoli per un lettore occasionale, quindi la migliore descrizione in questo momento sembra essere http://www.dartlang.org/articles/optional-types/ .

Ecco un esempio:

class Foo { }

main() {
  var foo = new Foo();
  if (foo is Foo) {
    print("it's a foo!");
  }
}

Sembra che non vi sia alcuna menzione di isoperatore nella specifica. È meglio fare riferimento al file grammaticale nelle fonti Dart: code.google.com/p/dart/source/browse/trunk/dart/language/…
Idolon

4
@Idolon, l' isoperatore è definito a pagina 59 delle specifiche, sezione 10.30 "Prova di tipo"
Duncan

4
ise is!può essere trovato nella sezione Operatori del tour linguistico di Dart.
Ricci

1
la nuova sintassi ègetTypeName(dynamic obj) => obj.runtimeType;
Mahdi Imani

1
!=ma is!... mi confonde non lo fa
atreeon

38

Il Objecttipo di dardo ha un runtimeTypemembro dell'istanza (la fonte è dalla dart-sdkv1.14, non so se era disponibile in precedenza)

class Object {
  //...
  external Type get runtimeType;
}

Utilizzo:

Object o = 'foo';
assert(o.runtimeType == String);

11
RuntimeType è solo a scopo di debug e il codice dell'applicazione non dovrebbe dipendere da esso. Può essere sovrascritto dalle classi per restituire valori falsi e probabilmente restituisce valori inutilizzabili quando trasferito in JS
Günter Zöchbauer

1
Grazie per il tuo commento, sono abbastanza nuovo per Dart e sono d'accordo che runtimeTypepotrebbe essere ignorato dalle classi, anche se non riesco a pensare a un motivo per cui lo farebbero. (il codice esterno non può impostare il valore poiché è un getter) Personalmente, mi atterrei a ise alla riflessione.
sbedulin

2
Va bene che questo sia menzionato qui. Non è molto ovvio che runtimeTypeabbia queste limitazioni.
Günter Zöchbauer

Gunter, è ancora il caso che runtimeTypedovrebbe essere usato solo per scopi di debug? Chiedo perché non c'è alcuna menzione di questo nei documenti per Object, o altrove (che ho potuto trovare).
Matt C

1
Il commento di @ GünterZöchbauer non è più vero in Dart 2. Dovrebbe andare bene usarlo ora.
vovahost

18

object.runtimeType restituisce il tipo di oggetto

Per esempio:

print("HELLO".runtimeType); //prints String
var x=0.0;
print(x.runtimeType); //prints double

7
La risposta di sbedulin lo spiega già. Non ha senso aggiungere la stessa risposta di quelle esistenti. Vedi anche i commenti sotto la sua risposta.
Günter Zöchbauer

17

Come altri hanno già detto, l' isoperatore di Dart è l'equivalente dell'operatore di Javascript instanceof. Tuttavia, non ho trovato un analogo diretto typeofdell'operatore in Dart.

Per fortuna l' API dart: mirrors reflection è stata recentemente aggiunta all'SDK ed è ora disponibile per il download nell'ultimo pacchetto Editor + SDK . Ecco una breve demo:

import 'dart:mirrors'; 

getTypeName(dynamic obj) {
  return reflect(obj).type.reflectedType.toString();
}

void main() {
  var val = "\"Dart is dynamically typed (with optional type annotations.)\"";
  if (val is String) {
    print("The value is a String, but I needed "
        "to check with an explicit condition.");
  }
  var typeName = getTypeName(val);
  print("\nThe mirrored type of the value is $typeName.");
}


è una buona soluzione ma abbiamo un errore: Unsupported operation: dart:mirrors is no longer supported for web apps
Mahdi Imani

@Lii Questa risposta è stata scritta per Ecma TC52. Vedere dart.dev/faq
Rob

11

Esistono due operatori per il test di tipo: E is Tverifica per E un'istanza di tipo T mentre i E is! Ttest per E no un'istanza di tipo T.

Nota che E is Objectè sempre vero ed null is Tè sempre falso a meno che T===Object.


Potresti spiegare cosa si intende con T===Object? Dart non ha l'operatore triplo uguale, ma hai scelto di usarlo piuttosto che doppio uguale, quindi presumo che la differenza abbia un significato.
Matt C

@ MattC Questo è stato scritto più di 7 anni fa! Penso che quello che volevo dire fosse null is Objectvero ma null is Tfalso per qualsiasi altro tipo T. tbh anche se non sono stato vicino a Dart da molti anni, quindi non posso esserne certo.
Duncan

2

Giusto per chiarire un po 'la differenza tra ise runtimeType. Come qualcuno ha già detto (e questo è stato testato con Dart V2 +) il seguente codice:

class Foo { 
  Type get runtimeType => String;
}
main() {
  var foo = new Foo();
  if (foo is Foo) {
    print("it's a foo!");
  }
  print("type is ${foo.runtimeType}");

}

produrrà:

it's a foo! 
type is String

Che è sbagliato. Ora, non riesco a vedere il motivo per cui si dovrebbe fare una cosa del genere ...

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.