他们似乎都可以在相同的情况下使用。在类型检查等方面是否有不同的表示或不同的细微之处?
答案 0 :(得分:18)
来自Dart Programming Language Specification, 3rd Edition州的类型动态部分:
类型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);
}
在运行时,我认为,您不应该看到任何差异。
答案 1 :(得分:15)
dynamic
的另一个观点是,它不是真正的类型 - 它是一种关闭类型检查并告诉静态类型系统“信任我,我知道我在做什么”的方法。写dynamic o;
声明一个未键入的变量 - 它被标记为“未经类型检查”。
当你写Object o = something;
时,你告诉系统它不能假设o
,除了它是Object
。您可以致电toString
和hashCode
,因为这些方法是在Object
上定义的,但如果您尝试o.foo()
,您会收到警告 - 它无法看到您可以做到这一点,因此它会警告您,您的代码可能错误。
如果你写dynamic o = something
,你告诉系统不要做任何事情,也不要检查任何事情。如果你写o.foo()
,它就不会警告你。你告诉它“与o
相关的任何事情都行!相信我,我知道我在做什么”,所以它认为o.foo()
没问题。
强大的力量带来了很大的责任 - 如果您禁用变量的类型检查,它会依赖于您,以确保您没有做错任何事情。
答案 2 :(得分:4)
为了增加Alexandre对实际差异的回答,两者之间也存在语义差异,使用正确的差异将有助于更好地将您的意图传达给其他程序员。
当您使用Object
时,您说您知道您正在使用的类型,它是Object
。例如:
int getHashCode(Object obj) {
return obj.hashCode;
}
由于hashCode
是Object
上的属性,我们使用Object
作为参数类型来指定该函数可以接受Object
类型的任何内容。
另一方面,使用dynamic
表示Dart系统无法正确表达您要使用的类型:
void setEmail(dynamic email) {
if (email is Email) {
_email = email;
} else if (email is String) {
_email = new Email.fromString(email);
}
}
由于Dart目前不支持联合类型,因此无法表达类型Email | String
,因此我们被迫使用dynamic
接受所有类型,然后只处理type是我们感兴趣的。
答案 3 :(得分:2)
使用动态,您可以访问其类型的方法和属性。但是 Object 不允许这样做。
示例:
class MyClass{
myFunction() => print("This works");
}
void main(){
dynamic a = new MyClass();
Object b = new MyClass();
a.myFunction(); // prints without error
b.myFunction(); // error comes saying myFunction isn't defined for b
}
答案 4 :(得分:1)
此外,我注意到扩展方法在动态模式下无法正常工作,但在对象上可以正常工作。
// I used to have the extension on dynamic and had
// problems that didn't occur when using the same extension on Object
extension UtilExtensions on Object {
bool get isStringNotEmpty => this is String && (this as String).isNotEmpty;
String get asStringNotEmpty => isStringNotEmpty ? this as String : null;
bool get isIntNotZero => this is int && (this as int) != 0;
int get asIntNotZero => isIntNotZero ? this as int : null;
Map<String, Object> get asPair {
if (this != null && this is Map) {
return (this as Map).cast<String, Object>();
}
return null;
}
Map<String, Object> get asFullPair {
if (this != null && this is Map) {
var ret = (this as Map).cast<String, Object>();
for (var key in ret.keys) {
var val = ret[key];
if (val is Map) {
ret[key] = val.asFullPair;
}
}
return ret;
}
return null;
}
}
答案 5 :(得分:0)
dynamic
不是类型,它只是禁用类型检查。
我认为dynamic
非常危险,应尽可能避免。直到在运行时使应用程序崩溃,此代码才会给您任何警告:
dynamic a = 2;
String b = a;
虽然此代码将给您一个错误“无法将'Object'类型的值分配给'String'类型的变量”
Object a = 2;
String b = a;