在scala中构建一个通用的强制转换函数

时间:2014-11-12 02:00:37

标签: scala generics reflection

我想构建一个函数来从属性文件,键/值对中读取设置,然后将其强制转换为预期的类型。如果给定的字段名称不存在,我们将获得特定T的默认值。这是可行的吗?

我在这里放了一些伪代码,想知道如何在scala反射的帮助下编写真正的代码。

def getField[T](fieldName: String): T =
{
  val value = getField(fieldName)

  if (value == null) {
    T match {
     case Int => 0
     case Boolean => false
     ...
     case _ => null
   }
  }
  else value.asInstanceOf[T]    
}

或者,如果字段未定位则抛出异常,这对我来说不是一个坏主意...     def getField [T](fieldName:String):T =     {       val value = getField(fieldName)

  if (value == null) {
    throw new Exception("error msg")
   }
  }
  else value.asInstanceOf[T]    
}

如果它返回Option [T](我在这里讨论Writing a generic cast function Scala),我知道怎么做。

3 个答案:

答案 0 :(得分:2)

我会使用隐式参数来传递默认值。它将为您提供100%类型安全+简单的方法来覆盖默认值,不仅适用于简单类型,还适用于任何其他类型。

  trait DefaultValue[T] {
    def default: T
  }

  object DefaultValue {
    def apply[T](value: T) = new DefaultValue[T] {
      val default: T = value
    }
  }

  trait LowLevelDefaultImplicits {
    implicit val intDefaultValue = DefaultValue[Int](0)
    implicit val booleanDefaultValue = DefaultValue[Boolean](false)
  }

  object MyDefaults extends LowLevelDefaultImplicits {
    // Easy to override defaults
    implicit val trueByDefault = DefaultValue[Boolean](true)
  }

  import MyDefaults._

  def readField(s: String): Any = ... some extern service call ...

  def getField[T: DefaultValue](fieldName: String): T =
  {
    val value = readField(fieldName)

    if (value == null)
      implicitly[DefaultValue[T]].default
    else
      value.asInstanceOf[T]
  }

  println(getField[Int]("aaa"))
  println(getField[Boolean]("aaa"))

结果:

0
true

^ - 正如您所看到的那样,默认的“false”被更高优先级的隐式覆盖。

一个缺点 - 您需要为所有类型T定义默认值。但我认为这是一个好处。通过为每种类型提供默认值,您可以删除“null”值。

答案 1 :(得分:-1)

您始终可以采用面向对象的方式:

case class GetField[A](default: A) {
  def apply(field: Any): A = try {
    field.asInstanceOf[A]
  } catch {
    case e: NullPointerException => ???
    case e: ClassCastException => default
  }
}

def readField(key: String): Any = ???

val field = readField("foo")
val bool = GetField(false)(field)
val int = GetField(0)(field)

答案 2 :(得分:-1)

只需使用

value.asInstanceOf[T]

如果valuenull,则会返回类型T的默认值。数字为0,布尔值为false,依此类推。这是在Scala规范中的某处指定的。