Dart 中 Object、Dynamic 和 Var 之间的区别?

Difference between Object, Dynamic and Var in Dart?

在 null-safety 之前有一个关于 dynamicvardiscussion。那么它们之间的Object?是什么?

  1. Object? == dynamic吗?
  2. var?dynamic? 怎么样?
  3. dynamic?dynamic 有区别吗?

我看到官方document关于null-safety,但是找不到相关话题。

  1. dynamic 是一种特殊类型,禁用静态类型检查。您可以尝试对 dynamic 类型调用 any 方法。如果对象最终没有这样的方法,那么它将导致运行时失败而不是编译时失败。

    Object? 是适合引用任何对象的基类型,包括null。与 dynamic 不同,它 静态类型检查的,因此如果您尝试调用其上的大多数方法而不显式检查运行时类型或不执行,您将获得编译时失败演员。

  2. var? 是无效语法。 var 不是类型;它在没有明确指定类型的情况下声明一个变量,从而允许推断类型。

    dynamic? 有效但多余。 (见#3。)

  3. 类型 dynamic 的变量已经可以包含 null,因此添加 ? 使其可为空是多余的。 Dart 分析器会告诉你。

3:关于dynamic vs dynamic?它们是一样的.

由于 dynamic 也表示可空类型,对于编译器来说它与 dynamic? 相同。

来自 :

You can also see the analyzer and runtime will call it dynamic even if we check the signature of a method declared to return dynamic?:

void main() {
  print(test.runtimeType); //runtimeType of the test function: () => dynamic
}

dynamic? test() { }

事实上,dart linter 的提示是 'unnecessary' 在 dynamic? 中使用 ?(如 Null?):

The '?' is unnecessary because 'dynamic' is nullable without it. (unnecessary_question_mark).

就我个人而言,我不明白为什么 dynamic? 仅通过提示进行报告(包括我在内的许多人都没有注意到)以保持其作为语法有效。

1:用 Object? 类型声明的变量的行为与指定类型的所有其他普通变量一样,例如 String? 等。因为每个 class -apart Nullnull 的类型)- 是 Object 的子class(因为在 Dart 中没有与对象相对的原始值,不像 Java; 在 Dart 中 nullintbool 也是对象。但是如果你不知道 Java),请忘记这个说明,一个变量声明为Object? 可以包含任何值。但是编译器只允许在空检查后访问对象的属性(toString()==()runtimeType 等)。

dynamic(或 dynamic?,见第 3 点)声明的变量改为允许访问任何 public 成员:编译器不会执行任何检查(除非 属性 以下划线开头 _,因为那样的话很明显它不是 public);如果您尝试访问一个不存在的成员,您将在运行时出现错误 Note1。此外,使用 dynamic 我们也放弃了空安全:dynamic 等同于 dynamic? (实际上问号可以被认为是隐含的,就好像它一直在那里一样)。

2:使用 varfinal - 如果你想要一个不可变的引用 - 没有声明类型,编译器检查分配给的值变量(实际上,如果变量没有立即初始化,则不允许省略类型)并将变量视为使用该类型声明的变量。

dynamic 在运行时:

'dynamic' 的一种可能导致混淆的用法是与泛型 classes 一起使用,因为 dynamic 作为参数类型 在运行时也存在:

dynamic obj = true;

obj 在运行时具有 bool 类型,但具有

List list = [bool];

list 在运行时有 List<dynamic> 类型。 但是,使用

var list2 = [true];

正确推断参数类型(list2 具有 List<bool> runtimeType)。

Note1 更准确地说,诸如 myDynamicVariable.nonexistentMember 之类的调用会导致对 noSuchMethod() 方法的调用物体; noSuchMethod() 也可以被覆盖而不抛出任何异常;但在 Dart 2 中这是一种罕见的做法。