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)
对象无法访问类的属性和方法,但使用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)
为了增加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用来接受所有类型,然后仅处理该类型是我们感兴趣的类型的情况。