Como realizar a verificação de tipo de tempo de execução no Dart?

103

Estados de especificação do Dart:

As informações de tipo reificado refletem os tipos de objetos em tempo de execução e podem sempre ser consultadas por construções dinâmicas de verificação de tipos (os análogos de instanceOf, casts, typecase etc. em outras linguagens).

Parece ótimo, mas não há um instanceofoperador semelhante. Então, como executamos a verificação de tipo em tempo de execução no Dart? É possível de alguma forma?

Idolon
fonte

Respostas:

147

O operador instanceof é chamado isno Dart. A especificação não é exatamente amigável para um leitor casual, então a melhor descrição agora parece ser http://www.dartlang.org/articles/optional-types/ .

Aqui está um exemplo:

class Foo { }

main() {
  var foo = new Foo();
  if (foo is Foo) {
    print("it's a foo!");
  }
}
Patrick
fonte
Parece que não há nenhuma menção de isoperador na especificação. É melhor consultar o arquivo de gramática nas fontes do DART
Idolon
4
@Idolon, o isoperador é definido na página 59 da especificação, seção 10.30 'Teste de tipo'
Duncan,
4
ise is!podem ser encontrados na seção Operadores do tour linguístico Dart.
Curly
1
a nova sintaxe égetTypeName(dynamic obj) => obj.runtimeType;
Mahdi Imani
1
!=mas is!... me confunde, não
atreeon
38

O Objecttipo de dardo tem um runtimeTypemembro de instância (a fonte é dart-sdkv1.14, não sei se estava disponível anteriormente)

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

Uso:

Object o = 'foo';
assert(o.runtimeType == String);
sbedulina
fonte
11
RuntimeType é apenas para fins de depuração e o código do aplicativo não deve depender dele. Ele pode ser substituído por classes para retornar valores falsos e provavelmente retorna valores inutilizáveis ​​quando transpilado para JS
Günter Zöchbauer
1
Obrigado por sua observação, sou muito novo no Dart e concordo que isso runtimeTypepode ser anulado por classes, embora não consiga pensar em uma razão para isso. (o código externo não pode definir o valor senão é um getter) Pessoalmente, gostaria de manter uma isreflexão.
sbedulin
2
É bom que isso seja mencionado aqui. Não é muito óbvio que runtimeTypetenha essas limitações.
Günter Zöchbauer
Gunter, ainda é o caso que runtimeTypedeve ser usado apenas para fins de depuração? Eu pergunto porque não há nenhuma menção disso nos documentos do Object, ou em outro lugar (que eu possa encontrar).
Matt C
1
O comentário de @GünterZöchbauer não é mais verdadeiro no Dart 2. Não há problema em usá-lo agora.
vovahost
18

object.runtimeType retorna o tipo de objeto

Por exemplo:

print("HELLO".runtimeType); //prints String
var x=0.0;
print(x.runtimeType); //prints double
Raj Yadav
fonte
7
A resposta do sbedulin já explica isso. Não adianta adicionar a mesma resposta que as existentes. Veja também os comentários abaixo de sua resposta.
Günter Zöchbauer
17

Como outros mencionaram, o isoperador do Dart é equivalente ao instanceofoperador do Javascript . No entanto, não encontrei um análogo direto da typeofoperadora no Dart.

Felizmente, a API de reflexão dart: mirrors foi adicionada recentemente ao SDK e agora está disponível para download no pacote Editor + SDK mais recente . Aqui está uma breve demonstração:

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.");
}
Roubar
fonte
é uma boa solução, mas temos erro: Unsupported operation: dart:mirrors is no longer supported for web apps
Mahdi Imani
@Lii Esta resposta foi escrita para Ecma TC52. Ver dart.dev/faq
Rob
11

Existem dois operadores para o teste de tipo: E is Ttesta para E uma instância do tipo T enquanto E is! Ttestes para E não é uma instância do tipo T.

Observe que E is Objecté sempre verdadeiro e null is Tsempre falso, a menos que T===Object.

Duncan
fonte
Você poderia explicar o que significa T===Object? O Dart não tem o operador triplo igual, mas você optou por usá-lo em vez de duplo igual, então presumo que a diferença seja significativa.
Matt C de
@MattC Isso foi escrito há mais de 7 anos! Acho que o que eu quis dizer é null is Objectque seria verdadeiro, mas null is Tfalso para qualquer outro tipo de T. tbh, embora eu não tenha estado perto de Dart por muitos anos, então não posso ter certeza.
Duncan
2

Só para esclarecer um pouco a diferença entre ise runtimeType. Como alguém já disse (e isso foi testado com Dart V2 +) o seguinte 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}");

}

irá produzir:

it's a foo! 
type is String

O que está errado. Agora, eu não consigo ver a razão pela qual alguém deveria fazer tal coisa ...

Edoardo
fonte