Jak sprawdzić typ środowiska uruchomieniowego w Dart?

110

Specyfikacja rzutek stwierdza:

Reifikowane informacje o typach odzwierciedlają typy obiektów w czasie wykonywania i mogą być zawsze sprawdzane przez dynamiczne konstrukcje sprawdzające typ (analogi instanceOf, rzutowania, typecase itp. W innych językach).

Brzmi świetnie, ale nie ma takiego instanceofoperatora. Jak więc sprawdzać typ w czasie wykonywania w Dart? Czy to w ogóle możliwe?

Idolon
źródło

Odpowiedzi:

160

Operator instanceof jest wywoływany isw Dart. Specyfikacja nie jest zbyt przyjazna dla zwykłego czytelnika, więc obecnie najlepszym opisem wydaje się być http://www.dartlang.org/articles/optional-types/ .

Oto przykład:

class Foo { }

main() {
  var foo = new Foo();
  if (foo is Foo) {
    print("it's a foo!");
  }
}
Patrick
źródło
Wygląda na to, że isw specyfikacji nie ma żadnej wzmianki o operatorze. Lepiej odnieść się do pliku gramatyki w źródłach Dart: code.google.com/p/dart/source/browse/trunk/dart/language/ ...
Idolon
4
@Idolon, isoperator jest zdefiniowany na stronie 59 specyfikacji, sekcja 10.30 `` Test typu ''
Duncan,
5
isi is!można je znaleźć w sekcji Operatorzy podczas wycieczki językowej Dart.
Curly
1
nowa składnia togetTypeName(dynamic obj) => obj.runtimeType;
Mahdi Imani
1
!=ale is!... dezorientuje mnie, ale nie
atreeon
41

ObjectTyp darta ma element runtimeTypeinstancji (źródło pochodzi z wersji dart-sdk1.14, nie wiem, czy było dostępne wcześniej)

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

Stosowanie:

Object o = 'foo';
assert(o.runtimeType == String);
sbedulina
źródło
11
RuntimeType służy tylko do debugowania i kod aplikacji nie powinien od niego zależeć. Klasy mogą go przesłonić, aby zwracały fałszywe wartości i prawdopodobnie zwracają bezużyteczne wartości po transpozycji do JS
Günter Zöchbauer
1
Dziękuję za uwagę, jestem całkiem nowy w Dart i zgadzam się, że runtimeTypezajęcia mogą zostać zastąpione przez zajęcia, chociaż nie mogę wymyślić powodu, dla którego by to zrobili. (kod zewnętrzny nie może ustawić wartości, ponieważ jest to getter) Osobiście trzymałbym się isi zastanawiał.
sbedulin
2
W porządku, że jest to tutaj wspomniane. Nie jest oczywiste, że runtimeTypema te ograniczenia.
Günter Zöchbauer
Gunter, czy nadal jest to przypadek, który runtimeTypepowinien być używany tylko do celów debugowania? Pytam, ponieważ nie ma żadnej wzmianki o tym w dokumentach dla Object lub gdzie indziej (które mogłem znaleźć).
Matt C
1
Komentarz @ GünterZöchbauer nie jest już prawdziwy w Dart 2. Teraz powinno być w porządku.
vovaost
22

object.runtimeType zwraca typ obiektu

Na przykład:

print("HELLO".runtimeType); //prints String
var x=0.0;
print(x.runtimeType); //prints double
Raj Yadav
źródło
7
Odpowiedź z sbeduliny już to wyjaśnia. Nie ma sensu dodawać tej samej odpowiedzi, co już istniejące. Zobacz także komentarze poniżej jego odpowiedzi.
Günter Zöchbauer
17

Jak wspominali inni, isoperator Darta jest odpowiednikiem instanceofoperatora Javascript . Jednak nie znalazłem bezpośredniego odpowiednika typeofoperatora w Dart.

Na szczęście interfejs API dart: mirrors reflection został niedawno dodany do SDK i jest teraz dostępny do pobrania w najnowszym pakiecie Editor + SDK . Oto krótkie 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.");
}
Obrabować
źródło
jest to dobre rozwiązanie, ale mamy błąd: Unsupported operation: dart:mirrors is no longer supported for web apps
Mahdi Imani
@Lii Ta odpowiedź została napisana dla Ecma TC52. Zobacz dart.dev/faq
Rob
12

Istnieją dwa operatory do testowania typu: E is Ttesty dla E instancji typu T, podczas gdy E is! Ttesty dla E, a nie instancji typu T.

Zauważ, że E is Objectjest to zawsze prawda i null is Tzawsze jest fałszem, chyba że T===Object.

Duncan
źródło
Czy mógłbyś wyjaśnić, co to znaczy T===Object? Dart nie ma operatora potrójnego równa się, ale zdecydowałeś się go użyć zamiast podwójnego równa się, więc zakładam, że różnica ma znaczenie.
Matt C,
@MattC To zostało napisane ponad 7 lat temu! Myślę, że to, co miałem na myśli, null is Objectbyłoby prawdziwe, ale null is Tfałszywe dla każdego innego typu T. tbh, chociaż nie byłem w pobliżu Dart od wielu lat, więc nie mogę być pewien.
Duncan
5

Żeby nieco wyjaśnić różnicę między isi runtimeType. Jak ktoś już powiedział (a to zostało przetestowane z Dart V2 +) następujący kod:

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

}

wyświetli:

it's a foo! 
type is String

Co jest złe. Teraz nie widzę powodu, dla którego należałoby to zrobić ...

Edoardo
źródło
0

Po prostu zadzwoń

print (unknownDataType.runtimeType)

na danych.

Alish Giri
źródło