我想构建一个函数来从属性文件,键/值对中读取设置,然后将其强制转换为预期的类型。如果给定的字段名称不存在,我们将获得特定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),我知道怎么做。
答案 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]
如果value
为null
,则会返回类型T
的默认值。数字为0,布尔值为false
,依此类推。这是在Scala规范中的某处指定的。