Dart中动态类型和静态类型的区别

7

有两个问题。 第一个问题, 以下是强类型。

String msg = "Hello world.";
msg = "Hello world again.";

同时,在下面动态展示

var msg = "Hello world.";
msg = "Hello world again.";

这两个“msg”之间有什么区别吗?

其次,如果我使用以下代码用“new”关键字初始化一个变量,

Map myMap = new Map;

为什么要指定变量"myMap"为Map实例(Map myMap),因为'new'关键字已经包含了相同的含义吗?所以,难道不可以只写:
myMap = new Map;

因为“new”关键字已经暗示了新初始化的变量既是变量类型又是Map类型,所以我不明白为什么通常“Map”关键字与变量名一起使用,甚至包括“var”也是如此。有人对这个(似乎有点冗余的)Dart语法有什么想法吗?
3个回答

4

关于第一个问题,每个msg变量包含的内容没有区别。

对于地图问题,指定在声明时构造的变量类型是为了允许一些小类的灵活性。举个例子,看下面的代码:

class SubMap extends Map {
  SubMap() : super();
}

Map map = new SubMap();

这里我们有一个变量map,它包含一个SubMap对象作为其值,但是我们允许它在以后的时间里包含Map类型(或其他子类Map的类型)的值。

Dart最重要的一点是它是可选类型的。当运行您的代码时,除非您在检查模式下运行,否则您的所有类型注释都不会有任何区别。类型注释的用途是帮助您的IDE和其他工具提供自动完成帮助、可能的警告等,而像Javascript这样的完全动态语言无法做到这一点。


太棒了,现在我明白了。谢谢@Michael Fenwick。 - Letsgo
注意:Dart 2没有检查/未检查模式(https://github.com/flutter/flutter/issues/21066) - George 2.0 Hope

3
String msg = "Hello world.";
msg = "Hello world again.";
msg = 1; // exception in checked mode - int can not be assigned to String.


var msg = "Hello world.";
msg = "Hello world again.";
msg = 1; // ok in checked mode

Checked mode是开发者模式,其中会检查类型注释,并在代码违反它们时创建运行时异常。

在未经检查的(生产)模式下,添加类型注释以及注释的内容都没有任何区别。这是出于性能原因,因为Checked mode会更慢。


2
声明语句Map myMap = new Map()有三个作用:
  • 声明一个名为myMap的变量,类型为Map
  • 使用Map构造函数创建一个新对象;
  • 将该对象分配给变量。
类型注解意味着myMap具有静态类型Map。 静态类型会在编译时提供一些警告,但不会在运行时更改任何内容。类型注解还会在检查模式中添加类型检查,在该模式下,对变量的任何赋值都会检查是否可分配给Map
您创建的对象可以是任何使用任何构造函数的对象。我经常使用new HashMap()而不是new Map() ,并将其分配给类型为Map的变量。
然后将对象分配给变量,如果在检查模式下,则类型检查成功。
该变量与用于初始化它的值无关。如果稍后将字符串分配给myMap变量,则在检查模式下会失败。
因此,这两个msg变量之间的区别在于其中一个具有静态类型和检查模式中的类型检查。对于您显示的代码,行为没有区别。
如果下一行是var y = msg + 42;,则类型化版本会发出警告(msg的静态类型为StringString.operator+的类型为String->String,因此42具有无效的参数类型),而非类型化版本不会警告您(msg的类型为dynamic,因此您可能知道自己正在做什么)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接