Scala上层类型边界和父类

pr1*_*001 3 types scala type-bounds

我真的很喜欢使用上层类型边界来为我的构造提供一些灵活性.但是,我真的不知道它背后的任何原理,因为我发现使用以下代码:

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
  }
}
Run Code Online (Sandbox Code Playgroud)

我试图让我的类可以使用子类,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
                         ^
Run Code Online (Sandbox Code Playgroud)

问题是,我认为,我定义的方式(以及何时?)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
}
Run Code Online (Sandbox Code Playgroud)

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

还是我完全吠叫错了树?谢谢!

Hei*_*ger 9

在Scala的参数化类型,默认情况下不变的,例如,对于Cage[A]一个Cage[Bird]不是一个Cage[Animal].但是你可以通过方差声明来制作类型协变甚至逆变,例如Cage[+A](a: A),这就是编译器试图在错误消息中告诉你的内容.

现在,并不总是可以使类型参数协变.这仅在类型变量仅用于所谓的正面事件时才有效.如果你的类是不可变的,那么换一种方法(不是100%正确).在你的情况下,它会工作.所以你要做的就是添加一个+定义Library:

class Library[+T <: Service](collection: Collection[T], actives: Actives[T])
Run Code Online (Sandbox Code Playgroud)


oxb*_*kes 5

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

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

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

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