从类型scala中获取类

时间:2014-07-30 16:40:47

标签: scala

在scala中,我希望能够说出

val user = Node.create[User](...) // return User object

所以这就是我到目前为止所做的:

def create[T : TypeTag](map: Map[String, Any]) {
    val type = typeOf[T]
    // create class from type here???
}

我一直在研究如何从泛型类创建类,并发现使用ClassManifest似乎已被弃用。相反,类型标签在这里,所以我能够做类似这种typeOf [T]的事情并且实际上得到了类型......但是我失去了。如果我可以获得该类,那么我可以使用类似class.newInstance的东西并从那里手动设置字段。

问题是:给定一个类型,我可以获得给定类型的类实例吗?

2 个答案:

答案 0 :(得分:6)

事实上最简单的方法是使用ClassTag

def create[T : ClassTag](map: Map[String, Any]): T = {
  val clazz: Class[_] = classTag[T].runtimeClass
  clazz.newInstance(<constructor arguments here>).asInstanceOf[T]
}

ClassTag是Java Class的一个瘦包装器,主要用于数组实例化。

TypeTag设施更强大。首先,您可以使用它来调用Java反射:

import scala.reflect.runtime.universe._

def create[T: TypeTag](map: Map[String, Any]): T = {
  val mirror = runtimeMirror(getClass.getClassLoader)  // current class classloader
  val clazz: Class[_] = mirror.runtimeClass(typeOf[T].typeSymbol.asClass)
  clazz.newInstance(<constructor arguments here>).asInstanceOf[T]
}

但是,Scala反射允许实例化类而不回退到Java反射:

def create[T: TypeTag](map: Map[String, Any]): T = {
  // obtain type symbol for the class, it is like Class but for Scala types
  val typeSym = typeOf[T].typeSymbol.asClass

  // obtain class mirror using runtime mirror for the given classloader
  val mirror = runtimeMirror(getClass.getClassLoader)  // current class classloader
  val cm = mirror.reflectClass(typeSym)

  // resolve class constructor using class mirror and 
  // a constructor declaration on the type symbol
  val ctor = typeSym.decl(termNames.CONSTRUCTOR).asMethod
  val ctorm = cm.reflectConstructor(cm)

  // invoke the constructor
  ctorm(<constructor arguments here>).asInstanceOf[T]
}

如果要创建具有重载构造函数的类,可能需要更多工作 - 您必须从声明列表中选择正确的构造函数,但基本思想是相同的。您可以阅读有关Scala反射here

的更多信息

答案 1 :(得分:1)

有一种方法可以使用反射:运行时反射或宏。关于运行时反射方式,您可以查看my blog post我尝试做的事情,就像您现在尝试做的那样。根据您的需要,对宏使用编译时反射可能是更好的选择。