Dartでランタイム型チェックを実行するにはどうすればよいですか?


103

Dart仕様には次のように記載されています。

具象化された型情報は、実行時のオブジェクトの型を反映し、動的な型チェック構造(他の言語のinstanceOf、キャスト、タイプケースなどの類似物)によって常に照会される場合があります。

素晴らしい音ですが、のinstanceofような演算子はありません。では、Dartでランタイム型チェックを実行するにはどうすればよいでしょうか。まったく可能ですか?

回答:


147

instanceof-operatorはisDart で呼び出されます。仕様は一般の読者にとって完全に友好的ではないため、現在のところ最も適切な説明はhttp://www.dartlang.org/articles/optional-types/のようです。

次に例を示します。

class Foo { }

main() {
  var foo = new Foo();
  if (foo is Foo) {
    print("it's a foo!");
  }
}

is仕様に演算子の記載がないようです。それはダート源で文法ファイルにREFEREすると良いでしょう:code.google.com/p/dart/source/browse/trunk/dart/language/...
Idolon

4
@Idolon、isオペレーターは仕様の59ページのセクション10.30「タイプテスト」で定義されています
Duncan

4
isそして、is!で見つけることができます演算子ダート言語ツアーのセクション。
Curly

1
新しい構文はgetTypeName(dynamic obj) => obj.runtimeType;
Mahdi Imani

1
!=しかしis!...私はそれをしないの混乱
atreeon

38

Dart ObjectタイプにはruntimeTypeインスタンスメンバーがあります(ソースはdart-sdkv1.14 からです。以前に利用可能であったかどうかは不明です)

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

使用法:

Object o = 'foo';
assert(o.runtimeType == String);

11
RuntimeTypeはデバッグ専用であり、アプリケーションコードはそれに依存すべきではありません。これは、戻り偽の値にクラスで上書きし、おそらくJSにtranspiled時に使用できない値を返すことができます
ギュンターZöchbauer

1
あなたの発言に感謝します。私はDartにかなり慣れていruntimeTypeないので、クラスによってオーバーライドされる可能性があることに同意しますが、その理由は考えられません。(外部コードはゲッターであるため、値を設定できません)個人的には、私は固執しisます。
sbedulin 2016年

2
これがここで言及されているのは問題ありません。runtimeTypeこれらの制限があることはそれほど明白ではありません。
ギュンターZöchbauer

ガンター、まだruntimeTypeデバッグ目的でのみ使用すべきケースですか?Objectのドキュメントや他の場所(私が見つけた可能性があります)でこれについての言及がないため、私は尋ねます。
マットC

1
@GünterZöchbauerコメントは、Dart 2ではもう当てはまりません。今すぐ使用しても問題ありません。
vovahost '13 / 11/19

18

object.runtimeType オブジェクトのタイプを返します

例えば:

print("HELLO".runtimeType); //prints String
var x=0.0;
print(x.runtimeType); //prints double

7
sbedulinからの回答はすでにそれを説明しています。既存のものと同じ答えを追加しても意味がありません。彼の回答の下のコメントも参照してください。
ギュンターZöchbauer

17

他の人が述べたように、Dartのis演算子はJavaScriptのinstanceof演算子と同等です。しかし、私はtypeofダートでオペレーターの直接の類似物を見つけていません。

ありがたいことに、dart:mirrorsリフレクションAPIが最近SDKに追加され、最新のEditor + SDKパッケージでダウンロードできるようになりました。ここに短いデモがあります:

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


それは良い解決策ですが、エラーがあります: Unsupported operation: dart:mirrors is no longer supported for web apps
Mahdi Imani

@Liiこの回答はEcma TC52用に書かれました。dart.dev/faqを
Rob

11

型テストには2つの演算子がありE is Tます。Eのテストは型TのインスタンスですがE is! T、Eのテストはそうではありません

E is Objectは常にtrueであり、でnull is Tない限り常にfalse であることに注意してくださいT===Object


とはどういう意味T===Objectですか?Dartには三重の等号演算子はありませんが、二重の等号ではなくそれを使用することを選択したので、違いに意味があると思います。
マットC

@MattCそれは7年以上前に書かれました!私がnull is Object言ったことは真実だと思いますがnull is T、他のタイプのT. tbhの場合は偽です。私は何年もダートの近くにいなかったので、確信が持てません。
ダンカン

2

ただ、ビットに違いを明確にするisととruntimeType。誰かがすでに言ったように(そしてこれはDart V2 +でテストされました)次のコード:

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

}

出力されます:

it's a foo! 
type is String

それは間違っています。今、なぜそんなことをしなければならないのか分からない…

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.