3

我真的很喜欢使用类型上限来为我的构造提供一些灵活性。但是,我真的不知道它背后的任何原理,正如我在以下代码中发现的那样:

object BoundsTest {
  abstract trait Service
  class Collection[T <: Service] extends collection.mutable.HashMap[Symbol, collection.mutable.Set[T]] with collection.mutable.MultiMap[Symbol, T]
  type Actives[T <: Service] = collection.mutable.HashMap[Symbol, T]
  class Library[T <: Service](collection: Collection[T], actives: Actives[T])
  private val libraries = new collection.mutable.HashMap[Symbol, Library[Service]]
  def setLibrary[T <: Service](name: Symbol, library: Library[T]) {
    libraries += name -> library
  }
}

我试图让我的类可以使用一个子类,Service只要它是一致的。但是,这不起作用:

$ scalac test.scala 
test.scala:10: error: type mismatch;
 found   : com.bubblefoundry.BoundsTest.Library[T]
 required: com.bubblefoundry.BoundsTest.Library[com.bubblefoundry.BoundsTest.Service]
Note: T <: com.bubblefoundry.BoundsTest.Service, but class Library is invariant in type T.
You may wish to define T as +T instead. (SLS 4.5)
    libraries += name -> library
                         ^

我认为,问题在于我如何(以及何时?)定义libraries,好像我进行了以下更改,一切都成功编译:

// private val libraries = new collection.mutable.HashMap[Symbol, Library[Service]]
def setLibrary[T <: Service](name: Symbol, library: Library[T]) {
  new collection.mutable.HashMap[Symbol, Library[T]] += name -> library
}

如何声明一个librariesHashMap 以使其具有多个Library具有不同Services 的 s?可以参考Service这里还是那不可能?

还是我完全在错误的树上吠叫?谢谢!

4

2 回答 2

10

在 Scala 中,参数化类型默认是不变的,例如Cage[A]a Cage[Bird]is not a Cage[Animal]。但是您可以通过变体声明使类型协变甚至逆变,例如Cage[+A](a: A),这就是编译器试图在错误消息中告诉您的内容。

现在并不总是可以使类型参数协变。这仅在类型变量仅用于所谓的正事件时才有效。如果你的类是不可变的,或者换一种方式(不是 100% 正确)。在你的情况下,它会起作用。因此,您所要做的就是在+的定义中添加一个Library

class Library[+T <: Service](collection: Collection[T], actives: Actives[T])
于 2011-09-13T08:59:55.393 回答
4

正如编译错误所说,该类Library是不变的。那是:

Library[S] <: Library[T]当且当S <: T

不成立。此属性称为协方差,是泛型类型参数的属性。这导致编译器错误的原因是您的 Map 期望Library[Service]作为它的值类型并且您正在尝试添加 a Library[T](由于缺乏协方差,它不是 a Library[Service],即使T <: Service

如果您的Library类是不可变的,那么您应该能够将 a 添加+到类型参数以指示scalac该库的类型协变的。

于 2011-09-13T09:04:06.147 回答