Wie führe ich eine Laufzeitüberprüfung in Dart durch?

101

Dartspezifikation besagt:

Reifizierte Typinformationen spiegeln die Objekttypen zur Laufzeit wider und können immer von dynamischen Typprüfungskonstrukten abgefragt werden (die Analoga von instanceOf, casts, typecase usw. in anderen Sprachen).

Hört sich toll an, aber es gibt keinen instanceofähnlichen Operator. Wie führen wir eine Laufzeit-Typprüfung in Dart durch? Ist das überhaupt möglich?

Idolon
quelle

Antworten:

145

Die Instanz des Operators wird isin Dart aufgerufen . Die Spezifikation ist nicht gerade für einen Gelegenheitsleser geeignet, daher scheint die derzeit beste Beschreibung http://www.dartlang.org/articles/optional-types/ zu sein .

Hier ist ein Beispiel:

class Foo { }

main() {
  var foo = new Foo();
  if (foo is Foo) {
    print("it's a foo!");
  }
}
Patrick
quelle
Anscheinend wird der isBediener in der Spezifikation überhaupt nicht erwähnt . Es ist besser, auf die Grammatikdatei in Dart-Quellen zu verweisen
Idolon
4
@Idolon, der isOperator ist auf Seite 59 der Spezifikation, Abschnitt 10.30 ' Typprüfung '
Duncan
4
isund is!finden Sie im Abschnitt Operatoren der Dart-Sprachtour.
Curly
1
neue Syntax istgetTypeName(dynamic obj) => obj.runtimeType;
Mahdi Imani
1
!=aber is!... verwirrt mich nicht
atreeon
37

Der Dart- ObjectTyp hat ein runtimeTypeInstanzmitglied (Quelle stammt aus dart-sdkVersion 1.14, weiß nicht, ob es früher verfügbar war)

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

Verwendung:

Object o = 'foo';
assert(o.runtimeType == String);
Sbedulin
quelle
11
RuntimeType dient nur zu Debugging-Zwecken und der Anwendungscode sollte nicht davon abhängen. Es kann von Klassen überschrieben werden, um gefälschte Werte zurückzugeben, und gibt wahrscheinlich unbrauchbare Werte zurück, wenn es an JS übertragen wird
Günter Zöchbauer
1
Vielen Dank für Ihre Bemerkung, ich bin ziemlich neu bei Dart und ich stimme zu, dass runtimeTypedies von Klassen überschrieben werden kann, obwohl ich mir keinen Grund vorstellen kann, warum sie es tun würden. (Externer Code kann den Wert nicht festlegen, da es sich um einen Getter handelt.) Persönlich würde ich mich an eine isReflexion halten.
Sbedulin
2
Es ist in Ordnung, dass dies hier erwähnt wird. Es ist nicht sehr offensichtlich, dass runtimeTypediese Einschränkungen bestehen.
Günter Zöchbauer
Gunter, sollte es immer noch runtimeTypenur zum Debuggen verwendet werden? Ich frage, weil dies in den Dokumenten für Object oder anderswo (die ich finden konnte) nicht erwähnt wird.
Matt C
1
@ GünterZöchbauer Kommentar ist in Dart 2 nicht mehr wahr. Es sollte in Ordnung sein, ihn jetzt zu verwenden.
Vovahost
18

object.runtimeType Gibt den Objekttyp zurück

Beispielsweise:

print("HELLO".runtimeType); //prints String
var x=0.0;
print(x.runtimeType); //prints double
Raj Yadav
quelle
7
Die Antwort von Sbedulin erklärt das bereits. Es macht keinen Sinn, dieselbe Antwort wie die vorhandenen hinzuzufügen. Siehe auch die Kommentare unter seiner Antwort.
Günter Zöchbauer
17

Wie andere bereits erwähnt haben, isentspricht der instanceofOperator von Dart dem Operator von Javascript . Ich habe jedoch kein direktes Analogon des typeofOperators in Dart gefunden.

Zum Glück wurde die Dart: Mirrors Reflection API kürzlich zum SDK hinzugefügt und steht jetzt im neuesten Editor + SDK-Paket zum Download zur Verfügung . Hier ist eine kurze 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.");
}
rauben
quelle
Es ist eine gute Lösung, aber wir haben Fehler: Unsupported operation: dart:mirrors is no longer supported for web apps
Mahdi Imani
@Lii Diese Antwort wurde für Ecma TC52 geschrieben. Siehe dart.dev/faq
Rob
11

Es gibt zwei Operatoren für die Typprüfung: E is TTests für E, eine Instanz vom Typ T, während E is! TTests für E keine Instanz vom Typ T sind.

Beachten Sie, dass dies E is Objectimmer wahr und null is Timmer falsch ist, es sei denn T===Object.

Duncan
quelle
Können Sie erklären, was damit gemeint ist T===Object? Dart hat den Operator Triple Equals nicht, aber Sie haben ihn anstelle von Double Equals verwendet. Ich gehe also davon aus, dass der Unterschied von Bedeutung ist.
Matt C
@MattC Das wurde vor mehr als 7 Jahren geschrieben! Ich denke, was ich meinte, null is Objectwäre wahr, aber null is Tfalsch für jeden anderen Typ T. tbh, obwohl ich seit vielen Jahren nicht mehr in der Nähe von Dart war, kann also nicht sicher sein.
Duncan
2

Nur um den Unterschied zwischen isund ein wenig zu verdeutlichen runtimeType. Wie schon jemand sagte (und dies wurde mit Dart V2 + getestet) den folgenden Code:

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

}

wird ausgegeben:

it's a foo! 
type is String

Was falsch ist. Jetzt kann ich den Grund nicht erkennen, warum man so etwas tun sollte ...

Edoardo
quelle