何时选择将给定函数的返回类型键入为 Seq
、Iterable
和 Traversable
(或者在 中更深入) Seq
的层次结构)?
你是如何做出这个决定的?我们有很多默认返回 Seq 的代码(通常从数据库查询和连续转换的结果开始)。我倾向于默认设置返回类型 Traversable
,并在特别期望给定顺序时设置 Seq
。但我没有充分的理由这样做。
我非常熟悉每个特征的定义,因此请不要回答定义术语。
最佳答案
这是一个好问题。您必须平衡两个问题:
- (1) 尽量保持 API 的通用性,以便稍后可以更改实现
- (2) 为调用者提供一些对集合执行的有用操作
其中 (1) 要求您对类型尽可能不具体(例如 Iterable
而不是 Seq
),而 (2) 要求您提供相反的信息。
即使返回类型只是Iterable
,您仍然可以返回一个Vector
,因此如果调用者希望获得额外的能力,它可以只调用.toSeq
或 .toIndexedSeq
,并且该操作对于 Vector
来说很便宜。
作为平衡的衡量标准,我想添加第三点:
- (3) 使用反射(reflect)数据组织方式的类型。例如。当您可以假设数据确实有序列时,请给出
Seq
。如果您可以假设不会出现两个相等的对象,请给出一个Set
。等等
这是我的经验法则:
- 尝试仅使用一小组集合:
Set
、Map
、Seq
、IndexedSeq
< - 不过,我经常违反之前的规则,使用
List
来支持Seq
。它允许调用者与 cons 提取器进行模式匹配 - 仅使用不可变类型(例如
collection.immutable.Set
、collection.immutable.IndexedSeq
) - 不使用具体实现 (
Vector
),而是使用提供相同 API 的通用类型 (IndexedSeq
) - 如果您封装一个可变结构,仅返回
Iterator
实例,调用者就可以轻松生成严格的结构,例如通过调用toList
来实现 - 如果您的 API 很小并且明确针对“大数据吞吐量”进行了调整,请使用
IndexedSeq
当然,这是我个人的选择,但我希望它听起来很合理。
关于scala,返回类型指南 - 当更喜欢 seq、可迭代、可遍历时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11702798/