如何从scala中的多态类型创建对象属性

如何从scala中的多态类型创建对象属性,scala,Scala,我试图创建一个对象来存储该对象创建的实例,并避免重新加载。我试图在对象上创建一个可变映射来存储它,但是我得到了一个编译错误 这是我的代码: class Bar class FooBar extends Bar object Foo { val loaded = scala.collection.mutable.Map[String, Bar]() def apply[T <: Bar](implicit m: Manifest[T]): T = { v

我试图创建一个对象来存储该对象创建的实例,并避免重新加载。我试图在对象上创建一个可变映射来存储它,但是我得到了一个编译错误

这是我的代码:

class Bar

class FooBar extends Bar

object Foo {
    val loaded = scala.collection.mutable.Map[String, Bar]()

    def apply[T <: Bar](implicit m: Manifest[T]): T = {
        val className = m.toString()
        if (loaded.contains(className)) {
            return loaded(className)
        }
        val instance = m.runtimeClass.newInstance().asInstanceOf[T]
        loaded(className) = instance
        instance
    }
}

还有另一种方法可以动态创建地图并传递T?或者以不同的方式解决此问题?

您的问题在于返回的是
已加载(className)
,其类型为
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])
  }
}
第二,最好的是:

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])
  }
}
导入scala.reflect.ClassTag
分类栏
类FooBar扩展了Bar
对象测试{
val classMap=scala.collection.mutable.Map[Class[\ux],Bar]()

def getInstance[T您可以使用
case-Some(bar:T)=>bar
,由于类标记的原因,我认为它匹配得很好。您还可以(也许更好)使用
getOrElseUpdate
@0\u,是的,您是对的。每天我都在学习有关Scala标准库的新知识)
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])
  }
}
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])
  }
}