¿Cómo realizar la verificación del tipo de tiempo de ejecución en Dart?

103

La especificación de dardo dice:

La información de tipo reificada refleja los tipos de objetos en tiempo de ejecución y siempre puede ser consultada por construcciones dinámicas de verificación de tipo (los análogos de instanceOf, casts, typecase, etc. en otros lenguajes).

Suena genial, pero no hay un instanceofoperador similar. Entonces, ¿cómo realizamos la verificación de tipos en tiempo de ejecución en Dart? ¿Es posible en absoluto?

Ídolo
fuente

Respuestas:

147

La instancia de operador se llama isen Dart. La especificación no es exactamente amigable para un lector casual, por lo que la mejor descripción en este momento parece ser http://www.dartlang.org/articles/optional-types/ .

He aquí un ejemplo:

class Foo { }

main() {
  var foo = new Foo();
  if (foo is Foo) {
    print("it's a foo!");
  }
}
Patricio
fuente
Parece que no se menciona el isoperador en absoluto en la especificación. Es mejor consultar el archivo de gramática en las fuentes de Dart: code.google.com/p/dart/source/browse/trunk/dart/language/…
Idolon
4
@Idolon, el isoperador se define en la página 59 de la especificación, sección 10.30 'Prueba de tipo'
Duncan
4
isy is!se puede encontrar en la sección Operadores del recorrido lingüístico de Dart.
Curly
1
la nueva sintaxis esgetTypeName(dynamic obj) => obj.runtimeType;
Mahdi Imani
1
!=pero is!... me confunde, no lo hace
atreeon
38

El Objecttipo de dardo tiene un runtimeTypemiembro de instancia (la fuente es de dart-sdkv1.14, no sé si estaba disponible antes)

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

Uso:

Object o = 'foo';
assert(o.runtimeType == String);
esbedulina
fuente
11
RuntimeType es solo para fines de depuración y el código de la aplicación no debería depender de él. Puede ser anulado por clases para devolver valores falsos y probablemente devuelva valores inutilizables cuando se transpila a JS
Günter Zöchbauer
1
Gracias por tu comentario, soy bastante nuevo en Dart y estoy de acuerdo en que runtimeTypelas clases pueden anularlo, aunque no puedo pensar en una razón por la que lo harían. (el código externo no puede establecer el valor porque es un captador) Personalmente, me apegaría a una isreflexión.
sbedulin
2
Está bien que esto se mencione aquí. No es muy obvio que runtimeTypetenga estas limitaciones.
Günter Zöchbauer
Gunter, ¿sigue siendo cierto que runtimeTypesolo debería utilizarse con fines de depuración? Lo pregunto porque no hay ninguna mención de esto en los documentos de Object, o en otro lugar (que pueda encontrar).
Matt C
1
El comentario de @ GünterZöchbauer ya no es cierto en Dart 2. Debería estar bien usarlo ahora.
vovahost
18

object.runtimeType devuelve el tipo de objeto

Por ejemplo:

print("HELLO".runtimeType); //prints String
var x=0.0;
print(x.runtimeType); //prints double
Raj Yadav
fuente
7
La respuesta de sbedulin ya lo explica. No tiene sentido agregar la misma respuesta que las existentes. Vea también los comentarios debajo de su respuesta.
Günter Zöchbauer
17

Como han mencionado otros, el isoperador de Dart es el equivalente al instanceofoperador de Javascript . Sin embargo, no he encontrado un análogo directo del typeofoperador en Dart.

Afortunadamente, la API de reflexión de dart: mirrors se ha agregado recientemente al SDK y ahora está disponible para descargar en el último paquete Editor + SDK . Aquí hay una breve demostración:

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.");
}
Robar
fuente
es una buena solución, pero tenemos un error: Unsupported operation: dart:mirrors is no longer supported for web apps
Mahdi Imani
@Lii Esta respuesta fue escrita para Ecma TC52. Ver dart.dev/faq
Rob
11

Hay dos operadores para las pruebas de tipo: E is Tprueba para E una instancia de tipo T mientras que E is! Tprueba para E no una instancia de tipo T.

Tenga en cuenta que E is Objectsiempre es cierto y null is Tsiempre es falso a menos que T===Object.

Duncan
fuente
¿Podría explicar qué se entiende por T===Object? Dart no tiene el operador triple igual, pero eligió usarlo en lugar de doble igual, así que supongo que la diferencia tiene importancia.
Matt C
@MattC ¡Eso fue escrito hace más de 7 años! Creo que lo que quise decir es null is Objectque sería cierto pero null is Tfalso para cualquier otro tipo T. tbh, aunque no he estado cerca de Dart durante muchos años, así que no puedo estar seguro.
Duncan
2

Solo para aclarar un poco la diferencia entre isy runtimeType. Como alguien dijo ya (y esto fue probado con Dart V2 +) el siguiente código:

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

}

dará salida:

it's a foo! 
type is String

Cuál está mal. Ahora, no veo la razón por la que uno debería hacer tal cosa ...

Edoardo
fuente