【问题标题】:Interface constraints in DartDart 中的接口约束
【发布时间】:2014-08-19 20:23:14
【问题描述】:

我正在将我的一个库从 Ruby 移植到 Dart,以感受一下这门语言,目前一切进展顺利。语言感觉还可以,没有太多粗糙的边缘。现在考虑到 Dart 是可选类型的,我可以给所有的东西一个动态类型并称之为一天,但这有点毫无意义。所以我一直在尽可能地添加类型,但有几个地方我不太清楚该怎么做。基本问题非常简单。我正在使用基本上具有以下界面的对象

abstract class Indexable {
  Matchable operator [](int index);
}

abstract class Matchable {
  bool operator ==(dynamic other);
}

现在几乎所有东西都支持Matchable,但并不是所有东西都支持Indexable,即使理论上很多东西都可以这样做。做明显的事情是行不通的。我不能只用as 进行类型转换,因为我的测试表明,当我尝试将Indexable 转换为Indexable 时,StringList 都会抛出异常。我能想到的其他解决方案是包装器和反射,但两者都感觉像是 hack,并添加了一大堆不必要的样板,因为 StringList 都已经实现了相关的运算符。

我想象的用例的一些伪代码

List<Matchable> matches(Indexable sequence, List<Matchable> matchers) {
  int index = 0;
  Matchable element;
  List<Matchable> accumulator = [];

  while ((element = sequence[index++]) != null) {
    if (matchers.any((m) => m == element)) {
      accumulator.add(element);
    }
  }

  return accumulator;
}

【问题讨论】:

    标签: types casting dart


    【解决方案1】:

    如果您想对不与其中的操作共享接口的类使用“通用”操作,则需要使用dynamic 作为类型或在使用它的位置进行动态类型检查if (x is String) something(x[index]); else if (x is List) ... .

    Dart 曾经有一个名为Sequence&lt;T&gt; 的类型,以T operator[](int index)int get length 作为接口。那是因为我们觉得它没有自己的重量,所以被删除了。实际上只有两个实现,ListString,而且 String 恰好匹配更像是一个意外 - 不建议在 String 上使用 [] 运算符,因为它会破坏代理对。

    在你的情况下,我只是将 List 用于 Indexable,并忽略 String 恰好也是 Indexable 的,除非原始程序依赖于它。

    【讨论】: