【问题标题】:Compatibility of argument types参数类型的兼容性
【发布时间】:2021-12-03 15:46:33
【问题描述】:

我想知道我的想法是正确的,还是我犯了一些大错误。让我们有简单的代码:

class A { String a = "a"; }

class B extends A { String b = "b"; }

void goofy(Map<String, A> map) {
  A? item = map["b1"];
  print(item?.a);
}

void croc(dynamic map) {
  final A? item = (map as Map<String, A>)["b1"];
  print(item?.a);
}

void frape(dynamic map) {
  final A? item = (map["b1"]) as A;
  print(item?.a);
}


void main() {
  Map<String, B> mapInst = {"b1":B()};
  goofy(mapInst);
  croc(mapInst);
  frape(mapInst);
  
  Map<String, A> mapInst2 = {"b1":A()};
  goofy(mapInst);
  croc(mapInst);
  frape(mapInst);
}

所有功能 goofycrocfrape 都按预期工作。但是我不太确定签名。 Map&lt;String,A&gt; 是否与 Map&lt;String,B&gt; 兼容,因为 B 继承自 A?或者这只是一个副作用,实际上基类型是 Map 并且没有考虑泛型很重要?当我想传递在通用签名中可以具有 A 或 B 类型的地图时,建议使用哪种语法?也许只是普通的地图?

【问题讨论】:

  • 如果数据类型不必是“安全”或已知的,我只会使用普通 Map
  • 我想要 Map,它的值继承自某个基类。但我不知道是否可以在 Dart 中表达这一点:/
  • 您可以使用动态来表示未知或可变类型。 Map 虽然它有自己的一系列问题。
  • 是的,但我正在寻找类似于 java 表示法 &lt;T super X&gt;&lt;T extends X&gt; 的东西,而不仅仅是可以吃掉所有东西的动态。

标签: flutter dart type-safety


【解决方案1】:

Map&lt;String,A&gt;Map&lt;String,B&gt; 兼容,因为 B 继承自 A

是的,如果B 没有从A 继承,代码将无法编译。

当我想传递通用签名中可以具有 A 或 B 类型的 Maps 时,建议使用哪种语法?

正如您在其中一个 cmets 中所说,您可以在类型参数上使用 extends 关键字

void myFunction<T extends A>(Map<String, T> map) { ... }

【讨论】:

    【解决方案2】:

    如果类Derived 派生自类Base,则Generic&lt;Derived&gt; 将被视为Generic&lt;Base&gt; 的子类型(更具体的类型)。

    Map&lt;String,A&gt; 是否与 Map&lt;String,B&gt; 兼容,因为 B 继承自 A?

    取决于您所说的“兼容”。 Map&lt;String, B&gt; 可替代 Map&lt;String, A&gt;。也就是说,您可以安全地传递 Map&lt;String, B&gt; ,其中预期 Map&lt;String, A&gt; 。但是,反过来是不安全的(因此需要显式转换)。

    当我想传递通用签名中可以具有 A 或 B 类型的 Maps 时,建议使用哪种语法?

    我会使用Map&lt;String, A&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-07
      • 2021-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-08
      相关资源
      最近更新 更多