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

时间:2015-07-07 00:10:53

标签: object dart dynamictype

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

6 个答案:

答案 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。您可以致电toStringhashCode,因为这些方法是在Object上定义的,但如果您尝试o.foo(),您会收到警告 - 它无法看到您可以做到这一点,因此它会警告您,您的代码可能错误。

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

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

答案 2 :(得分:4)

为了增加Alexandre对实际差异的回答,两者之间也存在语义差异,使用正确的差异将有助于更好地将您的意图传达给其他程序员。

当您使用Object时,您说您知道您正在使用的类型,它是Object。例如:

int getHashCode(Object obj) {
  return obj.hashCode;
}

由于hashCodeObject上的属性,我们使用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;