Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将字符串中的类型名称反映为Scala中的实际类型_Scala_Reflection_Types - Fatal编程技术网

将字符串中的类型名称反映为Scala中的实际类型

将字符串中的类型名称反映为Scala中的实际类型,scala,reflection,types,Scala,Reflection,Types,我有下面的类对象 class DefaultValue[+A](val default: A) object DefaultValue { implicit object DefaultDouble extends DefaultValue[Double](-1.0) implicit object DefaultFloat extends DefaultValue[Float](-1f) implicit object DefaultInt extends DefaultVal

我有下面的类对象

class DefaultValue[+A](val default: A)

object DefaultValue {

  implicit object DefaultDouble extends DefaultValue[Double](-1.0)
  implicit object DefaultFloat extends DefaultValue[Float](-1f)
  implicit object DefaultInt extends DefaultValue[Int](-1)
  implicit object DefaultBoolean extends DefaultValue[Boolean](false)

  def value[A](implicit value: DefaultValue[A]): A = value.default
}
要使用它,我调用
DefaultValue.value[Int]
DefaultValue.value[Double]

但是,当用户输入为
“Int”
时,我需要能够调用
DefaultValue.value[Int]
:以字符串形式写入的类型名,对于其他类型,也是如此

我希望在不进行模式匹配的情况下实现这一点,因为这基本上超出了在函数中插入TypeTag的目的。
有没有更好的方法可以做到这一点,或许可以使用Scala反射?

其中的一个问题是,您将无法获得良好的返回类型
Any
DefaultValue[\u]
是您可以获得的最佳值

您可以使用反射来编写如下内容:

import scala.reflect.runtime.{currentMirror => cm, universe => ru}

def defaultByTypename(typename: String): DefaultValue[_] = {
  val defaultValueName = "Default" + typename.trim.capitalize
  val objectSymbol = 
    ru.typeOf[DefaultValue.type].member(ru.TermName(defaultValueName))
  cm.reflectModule(objectSymbol.asModule).instance.asInstanceOf[DefaultValue[_]]
}
这将适用于
隐式对象
s。如果希望它与
隐式val
s一起使用(例如
隐式val DefaultString=new DefaultValue[String](“~”
),则必须为这种情况添加代码:

def defaultByTypename(typename: String): DefaultValue[_] = {
  val defaultValueName = "Default" + typename.trim.capitalize
  val objectSymbol = 
    ru.typeOf[DefaultValue.type].member(ru.TermName(defaultValueName))
  val result = if (objectSymbol.isModule) {
    cm.reflectModule(objectSymbol.asModule).instance
  } else if (objectSymbol.isTerm) {
    cm.reflect(DefaultValue).reflectField(objectSymbol.asTerm).get
  } else sys.error("Unknown typename")
  result.asInstanceOf[DefaultValue[_]]
}

但事实上,我认为,制作一张带有对应关系的
地图并不是一个坏主意:

val typename2DefaultValue = Map[String, DefaultValue[_]](
  "Double" -> DefaultDouble,
  "Float" -> DefaultFloat,
  "Int" -> DefaultInt,
  "Boolean" -> DefaultBoolean
)
这种方法可能更快,而且维护起来也不难。此外,还可以不要求对象名称和用户输入之间直接对应,或者为单个
DefaultValue
设置多个可能的字符串,等等


此外,如果将基类声明为
sealed
,并仅使用
对象扩展它,则可以简化此
映射的创建:

import scala.reflect.runtime.{currentMirror => cm, universe => ru}

sealed class DefaultValue[+A](val default: A)

object DefaultValue {
  implicit object DefaultDouble extends DefaultValue[Double](-1.0)
  implicit object DefaultFloat extends DefaultValue[Float](-1f)
  implicit object DefaultInt extends DefaultValue[Int](-1)
  implicit object DefaultBoolean extends DefaultValue[Boolean](false)

  val typename2DefaultValue: Map[String, DefaultValue[_]] = {
    val subclasses = ru.symbolOf[DefaultValue[_]].asClass.knownDirectSubclasses
    subclasses.map { subclass =>
      subclass.name.toString.stripPrefix("Default") ->
        cm.reflectModule(cm.staticModule(subclass.fullName)).instance.asInstanceOf[DefaultValue[_]]
    }.toMap
  }
}

谢谢你的详细回答。