飞镖中的动态和对象有什么区别?

use*_*898 24 object dynamictype dart

他们似乎都可以在相同的情况下使用它们.在类型检查等方面是否有不同的表示或不同的细微之处?

Ale*_*uin 27

本节类型动态从达特编程语言规范,第三版规定:

类型dynamic包含每个可能的标识符和arity的方法,以及命名参数的每种可能组合.这些方法都具有动态作为返回类型,并且它们的形式参数都具有动态类型.类型dynamic具有每个可能标识符的属性.这些属性都具有动态类型.

这意味着您不会通过调用dynamic类型变量上的任何方法来获得警告.对于变量类型而言,情况并非如此Object.例如:

dynamic a;
Object b;

main() {
  a = "";
  b = "";
  printLengths();
}

printLengths() {
  // no warning
  print(a.length);

  // warning:
  // The getter 'length' is not defined for the class 'Object'
  print(b.length);
}
Run Code Online (Sandbox Code Playgroud)

在运行时,我认为,你不应该看到任何差异.


lrn*_*lrn 22

另一个观点dynamic是,它不是真正的类型 - 它是一种关闭类型检查并告诉静态类型系统"信任我,我知道我在做什么"的方法.写入dynamic o;声明一个未键入的变量 - 它被标记为"未经类型检查".

当你写作时,Object o = something;你告诉系统它不能假设任何事情,o除非它是一个Object.您可以调用toString并且hashCode因为这些方法已定义Object,但如果您尝试这样做,o.foo()您将收到警告 - 它无法看到您可以执行此操作,因此它会警告您,您的代码可能是错误的.

如果你写的dynamic o = something话,你告诉系统不要做任何事情,也不要检查任何事情.如果你写,o.foo()那么它不会警告你.你告诉它"任何相关的东西o都行!相信我,我知道我在做什么",所以它认为没问题o.foo().

强大的功能带来了很大的责任 - 如果您禁用变量的类型检查,它会依赖于您,以确保您没有做错任何事情.


Edw*_*Liu 15

dynamic不是类型,它只是禁用类型检查。Object是所有不可空类型的“联合”,类型检查规则仍然适用。

比较这两种情况:

案例1(动态)

// a 'dynamic' variable can be assigned value of any type
dynamic a = 2;

// assign 'dynamic' value to any variable and code checker will not complain
int b = a;
// even when there is a bug
String c = a;
Run Code Online (Sandbox Code Playgroud)

案例2(对象)

// It is OK to assign a 'int' value to an 'Object' variable, because 'int' is a subtype of 'Object'
Object a = 2;

// will get type error: "A value of type 'Object' can't be assigned to a variable of type 'int'"
int b = a;

// typecast is required when assign a 'Object' value to a variale of one of its subtypes.
int c = a as int;
Run Code Online (Sandbox Code Playgroud)


bal*_*u k 6

对象无法访问类的属性和方法,但使用dynamic时可以访问它们。

检查这个例子:

class MyClass{
    myFunction() => print("This works");        
}

void main(){
dynamic a = new MyClass();
Object b = new MyClass();
a.myFunction(); // prints without error
b.myFunction(); // error : myFunction isn't defined for b
}
Run Code Online (Sandbox Code Playgroud)

  • 是的,这是有道理的,对于 Object,您使用 Object 引用来访问 MyClass 实例,当然该引用不知道该实例自己的方法。通过动态,您可以访问实际的 MyClass 引用,希望调用现有的方法。 (3认同)

Pix*_*ant 5

为了增加Alexandre关于实际差异的答案,两者之间还存在语义差异,使用正确的语义将有助于更好地与其他程序员交流您的意图。

使用时,Object您说的是知道要使用的类型,它就是Object。例如:

int getHashCode(Object obj) {
  return obj.hashCode;
}
Run Code Online (Sandbox Code Playgroud)

因为hashCode是的属性,Object我们将其Object用作参数类型以指定该函数可以接受任何类型的Object。

另一方面,using dynamic表示Dart系统无法正确表达您要使用的类型:

void setEmail(dynamic email) {
  if (email is Email) {
    _email = email;
  } else if (email is String) {
    _email = new Email.fromString(email);
  }
}
Run Code Online (Sandbox Code Playgroud)

由于Dart当前不支持联合类型,因此无法表达该类型,Email | String因此我们被迫dynamic用来接受所有类型,然后仅处理该类型是我们感兴趣的类型的情况。

  • 没有实际的区别,您可以将两者互换,程序将运行相同。当我提到“语义差异”时,是指其他Dart程序员将如何理解该代码。我对答案做了些微改动,以更好地反映这一点。 (3认同)