Scala - 自定义地图实现的正确类型

时间:2014-04-15 17:15:50

标签: scala types multimap

我正在尝试实现一个不可变的MultiMap(在我的例子中它也是排序的)。签名如下:

class SortedMultiMap[K,V] private (private val delegate: SortedMap[K, Set[V]])
                                  (implicit ord: Ordering[K])
      extends SortedMap[K, Set[V]]
      with SortedMapLike[K, Set[V], SortedMultiMap[K,V]]

如您所见,它将大多数操作委托给封装的委托映射。为MultiMap功能本身添加了一些额外的方法(类似于scala.collection.mutable.MultiMap)。如果您对完整的源代码感兴趣,请查看gist

除了+方法之外,我对我当前的实现感到满意:

期望的`+`实现

override def +[B1 >: Set[V]](kv: (K, B1)) = new SortedMultiMap(delegate + kv)

这会导致类型不匹配错误:found: (K, B1) required: (K, Set[V])有没有办法解决这个问题?如果我理解正确B1代表_ >: Set[V]

当前的`+`实现

目前的实施取自similar question about custom map implementation

override def +[B1 >: Set[V]](kv: (K, B1)): SortedMap[K, B1] = delegate + kv // general case
def +(kv: (K,Set[V])): SortedMultiMap[K, V] = new SortedMultiMap(delegate + kv) // specific case

这里提供了一般实现,并为特定情况提供了重载方法。这在手动调用方法时工作正常,但其他方法(如++updated等)也依赖于此方法,从而返回错误的集合(SortedMap而不是所需的{{ 1}})。

1 个答案:

答案 0 :(得分:1)

override def +[B1 >: Set[V]](kv: (K, B1)) = new SortedMultiMap(delegate + kv)

好吧,如果B1Object(满足Object :> Set[V]),然后将(K, Object)添加到delegate,您将获得SortedMap[K, Object],显然无法将其变为SortedMultiMap {1}}。如果您想避免这种情况,您有两种选择:

  1. 不展开SortedMap(您仍可以展开SortedMapLike)(不起作用,请参阅评论)。

  2. 匹配值的类型:

    override def +[B1 >: Set[V]](kv: (K, B1)): SortedMap[K, B1] = kv._2 match {
      // may need some massaging to persuade the compiler
      case v: Set[a] => new SortedMultiMap(delegate + (kv._1, v)) 
      case _ => delegate + kv
    }
    

    请注意,在这种情况下,静态返回类型始终为SortedMap

  3. 另一种方法是添加从SortedMap[K, Set[V]]SortedMultiMap[K,V]的隐式转换。这种方式如果B1Set[V],则结果仍为SortedMap,但您可以自由调用SortedMultiMap - 具体方法,或以其他方式使用SortedMultiMap预期