我真的很喜欢使用类型上限来为我的结构提供一些灵活性。但是,我真的不知道它背后的任何原则,因为我发现以下代码:
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
}
}
我试图让我的类(class)可以使用
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
}
我如何申报
libraries
HashMap 使得它有多个 Library
s 不同 Service
?可以引用Service
在这里还是不可能?还是我完全在错误的树上吠叫?谢谢!
最佳答案
在 Scala 中,参数化类型默认是不变的,例如为 Cage[A]
Cage[Bird]
不是 Cage[Animal]
.但是您可以通过方差声明来使类型协变甚至逆变,例如Cage[+A](a: A)
,这就是编译器试图在错误消息中告诉您的内容。
现在并不总是可以使类型参数协变。这仅在类型变量仅用于所谓的正发生时才有效。或者换一种方式(不是 100% 正确),如果你的类是不可变的。在你的情况下,它会起作用。所以你所要做的就是添加一个 +
到Library
的定义:
class Library[+T <: Service](collection: Collection[T], actives: Actives[T])
关于Scala 上类型边界和父类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7399044/