您的问题在于您返回loaded(className)
的是 type Bar
,而不是T
函数类型签名所要求的。不幸的是,您不能编码映射键和值类型之间的这种依赖关系,至少不能使用标准映射集合。您必须执行显式强制转换。这是一个工作示例:
import scala.reflect.ClassTag
class Bar
class FooBar extends Bar
object Test {
val classMap = scala.collection.mutable.Map[Class[_], Bar]()
def getInstance[T <: Bar : ClassTag]: T = {
val ct = implicitly[ClassTag[T]]
classMap get ct.runtimeClass match {
case Some(bar) => bar.asInstanceOf[T]
case None =>
val instance = ct.runtimeClass.newInstance().asInstanceOf[T]
classMap(ct.runtimeClass) = instance
instance
}
}
}
object Main {
def main(args: Array[String]) {
println(Test.getInstance[FooBar])
println(Test.getInstance[Bar])
println(Test.getInstance[FooBar])
}
}
请注意,我使用ClassTag
而不是Manifest
因为Manifest
已弃用。它的现代等价物是TypeTag
,但对于这项任务ClassTag
来说已经绰绰有余了。
更新
以下是@0__ 建议的代码变体。第一的:
import scala.reflect.ClassTag
class Bar
class FooBar extends Bar
object Test {
val classMap = scala.collection.mutable.Map[Class[_], Bar]()
def getInstance[T <: Bar : ClassTag]: T = {
val ct = implicitly[ClassTag[T]]
classMap get ct.runtimeClass match {
case Some(bar: T) => bar
case None =>
val instance = ct.runtimeClass.newInstance().asInstanceOf[T]
classMap(ct.runtimeClass) = instance
instance
}
}
}
object Main {
def main(args: Array[String]) {
println(Test.getInstance[FooBar])
println(Test.getInstance[Bar])
println(Test.getInstance[FooBar])
}
}
第二,最好的 IMO:
import scala.reflect.ClassTag
class Bar
class FooBar extends Bar
object Test {
val classMap = scala.collection.mutable.Map[Class[_], Bar]()
def getInstance[T <: Bar : ClassTag]: T = {
val ct = implicitly[ClassTag[T]]
classMap.getOrElseUpdate(ct.runtimeClass, ct.runtimeClass.newInstance().asInstanceOf[Bar]).asInstanceOf[T]
}
}
object Main {
def main(args: Array[String]) {
println(Test.getInstance[FooBar])
println(Test.getInstance[Bar])
println(Test.getInstance[FooBar])
}
}