Comment effectuer la vérification du type d'exécution dans Dart?

103

La spécification Dart indique:

Les informations de type réifié reflètent les types d'objets au moment de l'exécution et peuvent toujours être interrogées par des constructions de vérification de type dynamique (les analogues de instanceOf, casts, typecase, etc. dans d'autres langues).

Ça a l'air génial, mais il n'y a pas d' instanceofopérateur semblable à celui-ci. Alors, comment pouvons-nous effectuer la vérification de type à l'exécution dans Dart? Est-ce possible du tout?

Idolon
la source

Réponses:

147

L'opérateur instanceof est appelé isdans Dart. La spécification n'est pas vraiment conviviale pour un lecteur occasionnel, donc la meilleure description à l'heure actuelle semble être http://www.dartlang.org/articles/optional-types/ .

Voici un exemple:

class Foo { }

main() {
  var foo = new Foo();
  if (foo is Foo) {
    print("it's a foo!");
  }
}
Patrick
la source
Il semble qu'il n'y ait aucune mention d' isopérateur dans la spécification. Il est préférable de se référer au fichier de grammaire dans les sources Dart: code.google.com/p/dart/source/browse/trunk/dart/language/…
Idolon
4
@Idolon, l' isopérateur est défini à la page 59 de la spécification, section 10.30 `` Type test ''
Duncan
4
iset is!peut être trouvé dans la section Opérateurs de la visite linguistique de Dart.
Curly
1
nouvelle syntaxe estgetTypeName(dynamic obj) => obj.runtimeType;
Mahdi Imani
1
!=mais is!... me déroute pas ça fait
atreeon
38

Le Objecttype Dart a un runtimeTypemembre d'instance (la source est de la dart-sdkv1.14, je ne sais pas si elle était disponible plus tôt)

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

Usage:

Object o = 'foo';
assert(o.runtimeType == String);
sbéduline
la source
11
RuntimeType est uniquement à des fins de débogage et le code de l'application ne doit pas en dépendre. Il peut être remplacé par les classes pour renvoyer de fausses valeurs et renvoie probablement des valeurs inutilisables lorsqu'il est transpilé en JS
Günter Zöchbauer
1
Merci pour votre remarque, je suis assez nouveau sur Dart, et je suis d'accord que cela runtimeTypepeut être remplacé par des classes, même si je ne peux pas penser à une raison pour laquelle ils le feraient. (le code externe ne peut pas définir la valeur sinse c'est un getter) Personnellement, je m'en tiens à une isréflexion.
sbedulin
2
C'est bien cela est mentionné ici. Ce n'est pas très évident qui runtimeTypea ces limites.
Günter Zöchbauer
Gunter, est-ce toujours le cas qui runtimeTypene devrait être utilisé qu'à des fins de débogage? Je demande parce qu'il n'y a aucune mention de cela dans la documentation pour Object, ou ailleurs (que j'ai pu trouver).
Matt C
1
Le commentaire de @ GünterZöchbauer n'est plus vrai dans Dart 2. Il devrait être bien de l'utiliser maintenant.
vovahost
18

object.runtimeType renvoie le type d'objet

Par exemple:

print("HELLO".runtimeType); //prints String
var x=0.0;
print(x.runtimeType); //prints double
Raj Yadav
la source
7
La réponse de la sbeduline explique déjà cela. Il ne sert à rien d'ajouter la même réponse que les réponses existantes. Voir aussi les commentaires ci-dessous sa réponse.
Günter Zöchbauer
17

Comme d'autres l'ont mentionné, l' isopérateur de Dart est l'équivalent de l' instanceofopérateur de Javascript . Cependant, je n'ai pas trouvé d'analogue direct de l' typeofopérateur dans Dart.

Heureusement, l' API de réflexion dart: mirrors a récemment été ajoutée au SDK et est désormais disponible au téléchargement dans le dernier package Editor + SDK . Voici une courte démo:

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.");
}
Rob
la source
c'est une bonne solution mais, nous avons une erreur: Unsupported operation: dart:mirrors is no longer supported for web apps
Mahdi Imani
@Lii Cette réponse a été écrite pour Ecma TC52. Voir dart.dev/faq
Rob
11

Il existe deux opérateurs pour les tests de type: E is Tteste pour E une instance de type T tandis que E is! Tteste E pas une instance de type T.

Notez que E is Objectc'est toujours vrai et null is Ttoujours faux sauf T===Object.

Duncan
la source
Pourriez-vous expliquer ce que l'on entend par T===Object? Dart n'a pas l'opérateur triple égal, mais vous avez choisi de l'utiliser plutôt que double égal, donc je suppose que la différence a une signification.
Matt C
@MattC Cela a été écrit il y a plus de 7 ans! Je pense que ce que je voulais dire null is Objectserait vrai mais null is Tfaux pour tout autre type T. tbh bien que je ne sois pas près de Dart depuis de nombreuses années maintenant, donc je ne peux pas en être certain.
Duncan
2

Juste pour clarifier un peu la différence entre iset runtimeType. Comme quelqu'un l'a déjà dit (et cela a été testé avec Dart V2 +), le code suivant:

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

}

affichera:

it's a foo! 
type is String

Ce qui est faux. Maintenant, je ne vois pas la raison pour laquelle on devrait faire une telle chose ...

Edoardo
la source