【问题标题】:How to perform runtime type checking in Dart?如何在 Dart 中执行运行时类型检查?
【发布时间】:2011-12-04 16:22:23
【问题描述】:

Dart 规范声明:

具体的类型信息反映了运行时对象的类型,并且总是可以通过动态类型检查构造( instanceOf、casts、typecase 等在其他语言中的类似物)。

听起来不错,但没有类似instanceof 的运算符。那么我们如何在 Dart 中执行运行时类型检查呢?有可能吗?

【问题讨论】:

    标签: dynamic dart instanceof dart-mirrors


    【解决方案1】:

    在 Dart 中 instanceof-operator 被称为 is。该规范对普通读者并不完全友好,因此目前最好的描述似乎是http://www.dartlang.org/articles/optional-types/

    这是一个例子:

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

    【讨论】:

    • 看起来规范中根本没有提到is 运算符。最好参考 Dart 源码中的语法文件:code.google.com/p/dart/source/browse/trunk/dart/language/…
    • @Idolon,is 运算符在规范的第 59 页第 10.30 节“类型测试”中定义
    • isis! 可以在 Dart 语言导览的 Operators 部分找到。
    • 新语法是getTypeName(dynamic obj) => obj.runtimeType;
    • !=is!...让我感到困惑不是它确实
    【解决方案2】:

    Dart Object 类型有一个runtimeType 实例成员(来源来自dart-sdk v1.14,不知道之前是否可用)

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

    用法:

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

    【讨论】:

    • RuntimeType 仅用于调试目的,应用程序代码不应依赖它。它可以被类覆盖以返回假值,并且在转译为 JS 时可能返回不可用的值
    • 感谢您的评论,我对 Dart 很陌生,我同意 runtimeType 可能会被类覆盖,尽管我想不出他们会这样做的原因。 (外部代码无法设置值,因为它是一个吸气剂)就个人而言,我会坚持is 和反射。
    • 这里提到这个没关系。 runtimeType 有这些限制并不是很明显。
    • @GünterZöchbauer 评论在 Dart 2 中不再适用。现在可以使用它。
    • 我不确定他为什么认为 Dart 2 没问题。也许我错过了什么。
    【解决方案3】:

    正如其他人所提到的,Dart 的 is 运算符等同于 Javascript 的 instanceof 运算符。但是,我还没有在 Dart 中找到 typeof 运算符的直接类似物。

    谢天谢地,dart:mirrors reflection API 最近已添加到 SDK,现在可以在 latest Editor+SDK package 中下载。这是一个简短的演示:

    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
    • @Lii 这个答案是为 Ecma TC52 写的。见dart.dev/faq
    • 请注意,如果您使用 Flutter,它会禁用反射(因为它会破坏树抖动)。
    【解决方案4】:

    有两个用于类型测试的运算符:E is T 测试 E 类型 T 的实例,而 E is! T 测试 E 不是类型 T 的实例。

    请注意,E is Object 始终为真,null is T 始终为假,除非T===Object

    【讨论】:

    • 您能解释一下T===Object 的含义吗? Dart 没有三等号运算符,但您选择使用它而不是双等号,所以我认为差异很重要。
    • @MattC 那是 7 年前写的!我想我的意思是 null is Object 是真的,但 null is T 对于任何其他类型的 T 都是假的。虽然我已经很多年没有靠近 Dart 所以不能确定。
    【解决方案5】:

    精确的类型匹配是通过runtimeType 属性完成的。检查实例或其任何父类型(在继承链中)是否属于给定类型是通过is 运算符完成的:

    class xxx {}
    
    class yyy extends xxx {}
    
    void main() {
      var y = yyy();
      
      print(y is xxx);
      print(y.runtimeType == xxx);
    }
    

    返回:

    true
    false
    

    【讨论】:

      【解决方案6】:

      只是为了澄清isruntimeType 之间的区别。正如有人已经说过的(并且这是使用 Dart V2+ 测试的)以下代码:

      class Foo {
        @override
        Type get runtimeType => String;
      }
      main() {
        var foo = Foo();
        if (foo is Foo) {
          print("it's a foo!");
        }
        print("type is ${foo.runtimeType}");
        
      }
      

      将输出:

      it's a foo! 
      type is String
      

      这是错误的。 现在,我看不出为什么要这样做……

      【讨论】:

        【解决方案7】:

        只需调用

        print(unknownDataType.runtimeType)
        

        关于数据。

        【讨论】:

          【解决方案8】:

          print("请输入您的电话号码:\n"); var 电话号码 = stdin.readLineSync();

          if(phone number.runtimeType is int == true)     // checks if the values input are integers
          {
          print('you have successfully input your phone number!');
          }
          else{
          print('only numbers are allowed');
          }
          

          【讨论】:

          • 与大多数编程语言一样,您不需要添加== true,表达式本身会解析为布尔值。您只需要if (thing is int) - 然后您会看到您的解决方案实际上与接受的答案相同。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-11-02
          • 2020-06-20
          • 2020-12-27
          • 2023-03-09
          • 1970-01-01
          • 2018-02-10
          • 2016-09-09
          相关资源
          最近更新 更多