8

正如这个问题的标题所示:我的问题更多是关于形式(惯用惯例)而不是功能。简明扼要地说:

MyCollectionLike和之间的语义区别是什么MyCollection

StringLike例如:和StringMapLike和之间有什么区别Map。仔细查看 Scala API 文档,我可以看出它XLike通常是X. 但是,除此之外,我不清楚这些抽象层之间的语义差异。

在实践中,如果我正在创建一个新的类/特征,那么在我为该类选择名称时理解这种区别会很有帮助。

我遇到的具体问题如下:

我想创建 trait:SurjectiveMap[K, T]可以与Map[K, Set[T]]or混合使用MapLike[K, SetLike[T]]*Like鉴于我不知道and之间的语义差异*,我不确定该使用哪个。

4

2 回答 2

3

与 IFoo 和 Foo、Bar 和 BarImpl 之间的区别相同(除了 TraversableLike 是包含实现的超级特征):

Scala 集合库避免了代码重复,并通过在所谓的实现特征中使用泛型构建器和遍历集合来实现“相同结果类型”原则。这些特征以 Like 后缀命名;例如,IndexedSeqLike 是 IndexedSeq 的实现特征,类似地,TraversableLike 是 Traversable 的实现特征。诸如 Traversable 或 IndexedSeq 之类的集合类从这些特征继承了它们所有的具体方法实现。

来自Scala 集合架构

于 2013-05-29T21:33:49.417 回答
1

我认为使用Like特征可以让您改进返回(表示)类型。这涉及更多的工作。相比:

import collection.generic.CanBuildFrom

object FooMap {
  type Coll = FooMap[_, _]
  implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), FooMap[A, B]] = ???
}
trait FooMap[A, +B] extends Map[A, B] {
  def foo = 33
}

def test(f: FooMap[Any, Any]) {
  f.map(identity).foo  // nope, we ended up with a regular `Map`
}

相对

object FooMap extends collection.generic.ImmutableMapFactory[FooMap] {
  override type Coll = FooMap[_, _]
  implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), FooMap[A, B]] = ???
  def empty[A, B]: FooMap[A, B] = ???
}
trait FooMap[A, +B] extends Map[A, B] 
  with collection.immutable.MapLike[A, B, FooMap[A, B]] {

  def foo = 33
  override def empty: FooMap[A, B] = FooMap.empty[A, B]
}

def test(f: FooMap[Any, Any]) {
  f.map(identity).foo  // yes
}

MapLike必须在 trait 之后混入traitMap才能启动正确的返回类型。


看起来你仍然没有免费获得所有东西,例如你需要覆盖更多的方法:

override def +[B1 >: B](kv: (A, B1)): FooMap[A, B1]  // etc.
于 2013-05-30T00:46:19.037 回答