在 Dart 中,List.from 和 .of 以及 Map.from 和 .of 有啥区别?

Posted

技术标签:

【中文标题】在 Dart 中,List.from 和 .of 以及 Map.from 和 .of 有啥区别?【英文标题】:In Dart, what's the difference between List.from and .of, and between Map.from and .of?在 Dart 中,List.from 和 .of 以及 Map.from 和 .of 有什么区别? 【发布时间】:2018-10-23 12:25:30 【问题描述】:

在 Dart 中,List.fromList.of 以及 Map.fromMap.of 之间有什么区别?他们的文档并不完全清楚:

/**
* Creates a [LinkedHashMap] instance that contains all key/value pairs of
* [other].
*
* The keys must all be instances of [K] and the values of [V].
* The [other] map itself can have any type.
*
* A `LinkedHashMap` requires the keys to implement compatible
* `operator==` and `hashCode`, and it allows `null` as a key.
* It iterates in key insertion order.
*/
factory Map.from(Map other) = LinkedHashMap<K, V>.from;

/**
* Creates a [LinkedHashMap] with the same keys and values as [other].
*
* A `LinkedHashMap` requires the keys to implement compatible
* `operator==` and `hashCode`, and it allows `null` as a key.
* It iterates in key insertion order.
*/
factory Map.of(Map<K, V> other) = LinkedHashMap<K, V>.of;

/**
* Creates a list containing all [elements].
*
* The [Iterator] of [elements] provides the order of the elements.
*
* All the [elements] should be instances of [E].
* The `elements` iterable itself may have any element type, so this
* constructor can be used to down-cast a `List`, for example as:
* ```dart
* List<SuperType> superList = ...;
* List<SubType> subList =
*     new List<SubType>.from(superList.whereType<SubType>());
* ```
*
* This constructor creates a growable list when [growable] is true;
* otherwise, it returns a fixed-length list.
*/
external factory List.from(Iterable elements, bool growable: true);

/**
* Creates a list from [elements].
*
* The [Iterator] of [elements] provides the order of the elements.
*
* This constructor creates a growable list when [growable] is true;
* otherwise, it returns a fixed-length list.
*/
factory List.of(Iterable<E> elements, bool growable: true) =>
  new List<E>.from(elements, growable: growable);

差异与泛型有关吗?也许.from 工厂可以让您更改列表的类型,而.of 则不能?我来自 Java 背景,它适用于类型擦除,也许类型在 Dart 中被具体化,你不能使用强制转换或原始类型来更改列表/映射类型?

【问题讨论】:

【参考方案1】:

如果可能,现在最好使用集合文字而不是 .from.of 构造函数。显然,这有一些性能优势。 (见底部链接。)

例子:

something.toList() [...something]

例外:

如果需要向下转换,可以使用.from

但是,如果您确实使用它们,则应始终包含类型。

来源: Dart team engineer's post

【讨论】:

要使用List.of 创建一个固定长度的集合,您仍然需要将growable: false 作为参数传递,那么使用toList(growable: false) 不是比使用List.of(..., growable: false) 更好吗? @CopsOnRoad 我也在这么想,但从链接的帖子和 cmets 中我并不清楚。现在似乎什么都不需要.of 是的,List.of() 在我阅读了那个链接的帖子之后现在没有任何意义。【参考方案2】:

fromof 方法之间的重要区别在于后者具有类型注释而前者没有。由于 Dart 泛型被具体化并且 Dart 2 是强类型的,这是确保正确构造 List/Map 的关键:

List<String> foo = new List.from(<int>[1, 2, 3]); // okay until runtime.
List<String> bar = new List.of(<int>[1, 2, 3]); // analysis error

并确保正确推断类型:

var foo = new List.from(<int>[1, 2, 3]); // List<dynamic>
var bar = new List.of(<int>[1, 2, 3]); // List<int>

在 Dart 1 中,类型是完全可选的,因此许多 API 没有类型或部分类型。 List.fromMap.from 是很好的例子,因为传递给它们的 Iterable/Map 没有类型参数。有时 Dart 可以知道这个对象的类型应该是什么,但有时它只是以 List&lt;dynamic&gt;Map&lt;dynamic, dynamic&gt; 结束。

在 Dart 2 中,dynamic 类型从顶部(Object)和底部(null)类型更改为仅作为顶部类型。因此,如果您在 Dart 1 中意外创建了 List&lt;dynamic&gt;,您仍然可以将其传递给需要 List&lt;String&gt; 的方法。但在 Dart 2 中,List&lt;dynamic&gt;List&lt;Object&gt; 几乎相同,所以这会失败。

如果您使用的是 Dart 2,则应始终使用这些 API 的类型化版本。为什么旧的仍然存在,那里的计划是什么?我真的不知道。我猜想随着时间的推移,它们将与 Dart 1 的其余部分一起被淘汰。

【讨论】:

如果您想丢弃类型信息,也许List.from 有用?就像List.from 文档中给出的示例一样:List&lt;SubType&gt; subList = new List&lt;SubType&gt;.from(superList.whereType&lt;SubType&gt;());List.of 无法做到这一点? 你可以用List.from 做的所有事情你都可以用List.of 做。在这个例子中, List sublist = new List.of(superList.whereType()) 那么方法文档应该更新。根本不清楚。谢谢。 值得在 dart sdk repo 上提出一个问题,但我也认为样式指南将从 2.0 更新。这些构造函数的存在可能只是为了使迁移更容易 为什么List.from 没有被标记为弃用呢?

以上是关于在 Dart 中,List.from 和 .of 以及 Map.from 和 .of 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 Provider.of(context) 调用类方法

从另一个文件中调用一个Object

flutter Dart Packages包导入报错:Target of URI doesn‘t exist ‘package:xxxxx‘ 解决方法

Dart 的编程语言之美 4 个超级特性

Flutter/Dart - 延迟后打开视图

用随机投掷飞镖法计算Pi值(Randomness Throwing dart Pi Python)