【问题标题】:Why are incorrect type assignments allowed in Dart?为什么 Dart 中允许不正确的类型赋值?
【发布时间】:2016-01-30 04:22:31
【问题描述】:

我知道类型在 Dart 中几乎是可选的,但如果我选择指定变量类型,我希望像 int i = "abc" 这样的赋值会在运行时引发错误。然而,无论是那个还是以下任何一个都不会引发错误,它们只是忽略了类型转换。

  String str     = "test";
  int integer    = 5;
  double decimal = 1.5;
  List list      = [1,2,3];

  String s = decimal;   print(s);  // 1.5
  int i    = str;       print(i);  // test
  double d = list;      print(d);  // [1, 2, 3]
  List l   = integer;   print(l);  // 5

this tutorial我发现,它说:

但是下面的 sn-p 会产生错误,因为编译器将 b 识别为 int 被错误地分配了 double 值。这是实际的类型检查,也是 Dart 对 JavaScript 进行改进的众多方式之一。

int b=7898765;

b = 9.8; // 错误不能将 double 赋值给 int

但是,在使用 Dartium 或使用 <script src="packages/browser/dart.js"></script> 时,该代码不会对我产生错误。

如果我做var i = "abc" + 1.5,它会抛出一个错误,那么为什么类型错误分配不做同样的事情呢?这是疏忽还是设计选择?如果是后者,原因是什么?

提前致谢。

【问题讨论】:

    标签: dart dartium


    【解决方案1】:

    此答案仅适用于 Dart 1.x

    在生产模式下运行时,Dart 类型的注释会被忽略(默认)。如果您在检查模式下运行,则检查类型。如果您在实例上调用不存在的方法,仍然会引发异常。

    var i = "abc" + 1.5
    

    + 运算符(方法)显然会对参数进行类型检查并抛出,因为它不是非字符串值。

    对于从 Dart 生成的 JS,您可以通过添加配置 $dart2js 转换器以生成“检查模式”输出

    transformers:
    - $dart2js:
        checked: true
    

    到您的pubspec.yaml 文件(有关更多$dart2js 选项,请参阅Configuring the Built-in dart2js Transformer for Pub)。 这仅在您使用pub build 构建时生效。如果您直接使用dart2js 生成JS,则传递-c 标志以创建检查模式输出。

    对于在服务器 VM 上运行的代码,还要传递 -c 标志,如

    dart -c your_script.dart
    

    在您的问题中,您没有提供有关如何运行 Dart 脚本或如何生成 JS 的任何信息。

    在这个简单的DartPad 中,编辑器显示来自静态分析的错误,这是添加类型注释的另一个用例。

    【讨论】:

    • 谢谢! Checked模式很好了解,我会在开发时使用它。我现在只是尝试使用选中的标志启动 Dartium,看看它做了什么(在 Windows 上,所以它给了我一些态度)。至于如何生成 JS,我现在使用的是 Dartium,因为我讨厌通过生成的代码进行调试,但通常我只使用 Chrome 开发编辑器。
    • 例如,如果您使用 WebStorm,在 Dartium 或服务器端脚本中调试时,检查模式始终是默认模式。
    • 如果这回答了您的问题,请接受。您需要更多信息吗?
    • 虽然您的回答很有帮助,而且很高兴知道我可以使用检查模式调试我的代码,但我的问题更多的是关于语言设计决策。我不明白他们为什么选择不将类型错误分配默认为错误,因为它看起来应该是这样。我仍然为你 +1,但这更多是我好奇的。
    • 没关系。我只是想知道您的问题是否已完全回答,或者您是否只是忘记接受;-)。 Dart 具有独特的设计/理念。例如,这里是 Dart 语言设计者bracha.org/pluggableTypesPosition.pdf 的一篇论文。另请参阅dartlang.org/articles/optional-types 正如我在回答中所写的,类型注释通常在运行时被忽略。这是一个基本的 Dart 设计决策。 Checked 模式是一种开发工具,允许验证类型注释是否真正符合运行时分配的实际类型。
    【解决方案2】:

    Dart 2.6 拒绝此代码。

    A value of type 'double' can't be assigned to a variable of type 'String'
    

    https://dartpad.dev/10ebe4bb74a11fe6e68efb351af40d1a

    我还测试了Map<String, dynamic>(为了更好地理解JSON deserialization pattern

    void main() {
      Map<String, dynamic> map = {
        'str': 'test',
        'integer': 5,
        'decimal': 1.5,
        'list': [1,2,3]
      };
    
      String s = map['decimal'];   print(s);  // JSDouble not String
      int i    = map['str'];       print(i);  // JSString not int
      double d = map['list'];      print(d);  // JSArray not double
      List l   = map['integer'];   print(l);  // JSInt not List
    }
    

    https://dartpad.dev/7bc355b3b7779d2b37e1aae2b6def050

    这在运行时也会失败,给出诸如

    之类的错误
    TypeError: 1.5: type 'JSDouble' is not a subtype of type 'String'
    

    【讨论】:

      猜你喜欢
      • 2018-10-09
      • 1970-01-01
      • 2013-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-02
      • 2014-03-01
      • 1970-01-01
      相关资源
      最近更新 更多