จะทำการตรวจสอบประเภทรันไทม์ใน Dart ได้อย่างไร?


118

สถานะข้อกำหนดของ Dart:

ข้อมูลประเภท Reified สะท้อนถึงประเภทของอ็อบเจ็กต์ในขณะรันไทม์และอาจถูกสอบถามโดยโครงสร้างการตรวจสอบการพิมพ์แบบไดนามิก (แอนะล็อกของ instanceOf, casts, typecase เป็นต้นในภาษาอื่น ๆ )

ฟังดูดี แต่ไม่มีinstanceofตัวดำเนินการที่เหมือน แล้วเราจะทำการตรวจสอบประเภทรันไทม์ใน Dart ได้อย่างไร? เป็นไปได้หรือไม่

คำตอบ:


170

อินสแตนซ์ของตัวดำเนินการถูกเรียกisใน Dart ข้อมูลจำเพาะไม่ตรงที่เป็นมิตรกับผู้อ่านสบาย ๆ เพื่อให้คำอธิบายที่ดีที่สุดในขณะนี้ดูเหมือนว่าจะhttp://www.dartlang.org/articles/optional-types/

นี่คือตัวอย่าง:

class Foo { }

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

4
@Idolon ตัวisดำเนินการถูกกำหนดไว้ในหน้า 59 ของข้อมูลจำเพาะส่วน 10.30 'การทดสอบประเภท'
Duncan

6
isและis!สามารถพบได้ในส่วนOperatorsของทัวร์ภาษา Dart
Curly

1
ไวยากรณ์ใหม่คือgetTypeName(dynamic obj) => obj.runtimeType;
Mahdi Imani

1
!=แต่is!... ทำให้ฉันสับสนไม่ได้
atreeon

1
ทัวร์ภาษา Dart มีส่วนเกี่ยวกับตัวดำเนินการที่เท่าเทียมกัน: dart.dev/guides/language/…และประเภทโอเปอเรเตอร์: dart.dev/guides/language/language-tour#type-test-operators
Yudhishthir Singh

43

ObjectประเภทDart มีruntimeTypeสมาชิกอินสแตนซ์ (แหล่งที่มาจากdart-sdkv1.14 ไม่ทราบว่ามีให้ก่อนหน้านี้หรือไม่)

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

การใช้งาน:

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

12
RuntimeType ใช้สำหรับการดีบักเท่านั้นและรหัสแอปพลิเคชันไม่ควรขึ้นอยู่กับมัน สามารถถูกแทนที่โดยคลาสเพื่อส่งคืนค่าปลอมและอาจส่งคืนค่าที่ใช้ไม่ได้เมื่อเปลี่ยนเป็น JS
GünterZöchbauer

1
ขอบคุณสำหรับคำพูดของคุณฉันยังใหม่กับ Dart และฉันยอมรับว่าruntimeTypeชั้นเรียนอาจถูกครอบงำแม้ว่าฉันจะคิดไม่ออกว่าทำไมถึงเป็นเช่นนั้น (รหัสภายนอกไม่สามารถกำหนดค่าได้มันเป็นตัวรับ) โดยส่วนตัวแล้วฉันจะยึดติดisและไตร่ตรอง
sbedulin

2
เป็นเรื่องปกติที่จะกล่าวถึงที่นี่ ไม่ชัดเจนว่าruntimeTypeมีข้อ จำกัด เหล่านี้
GünterZöchbauer

Gunter ยังคงเป็นกรณีที่runtimeTypeควรใช้เพื่อการดีบักเท่านั้นหรือไม่? ฉันถามเพราะไม่มีการพูดถึงสิ่งนี้ในเอกสารสำหรับ Object หรือที่อื่น ๆ (ที่ฉันหาได้)
Matt C

1
ความคิดเห็นของ @ GünterZöchbauerไม่เป็นความจริงอีกต่อไปในโผ 2 ควรใช้ตอนนี้ได้
vovahost

23

object.runtimeType ส่งคืนประเภทของวัตถุ

ตัวอย่างเช่น:

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

9
คำตอบจาก sbedulin อธิบายไว้แล้ว ไม่มีประเด็นในการเพิ่มคำตอบเดียวกับคำตอบที่มีอยู่ ดูความคิดเห็นด้านล่างคำตอบของเขาด้วย
GünterZöchbauer

17

เป็นคนอื่นได้กล่าวถึงโผisผู้ประกอบการจะมีค่าเท่ากับ Javascript ของinstanceofผู้ประกอบการ อย่างไรก็ตามฉันไม่พบอะนาล็อกโดยตรงของตัวtypeofดำเนินการใน Dart

โชคดีที่dart: mirrors reflect 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

13

มีตัวดำเนินการสองตัวสำหรับการทดสอบประเภท: E is Tการทดสอบสำหรับ E เป็นอินสแตนซ์ประเภท T ในขณะที่E is! Tการทดสอบสำหรับ E ไม่ใช่อินสแตนซ์ประเภท T

ทราบว่าE is Objectเป็นจริงเสมอและมักจะเป็นเท็จเว้นแต่null is TT===Object


คุณช่วยอธิบายความหมายโดยT===Object? Dart ไม่มีตัวดำเนินการ triple เท่ากับ แต่คุณเลือกที่จะใช้มากกว่า double เท่ากับดังนั้นฉันถือว่าความแตกต่างมีนัยสำคัญ
Matt C

@MattC ที่เขียนมากว่า 7 ปีแล้ว! ฉันคิดว่าสิ่งที่ฉันหมายถึงมันnull is Objectน่าจะเป็นจริง แต่null is Tเป็นเท็จสำหรับประเภทอื่น ๆ T. tbh แม้ว่าฉันจะไม่ได้อยู่ใกล้ Dart มาหลายปีแล้วดังนั้นก็ไม่สามารถมั่นใจได้
Duncan

5

เพียงชี้แจงบิตแตกต่างระหว่างและ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.