这会返回Any
:
def convertType(data: String, dataType: String) = {
dataType match {
case "Int" => data.toInt
case "Double" => data.toDouble
case "Long" => data.toLong
case "Option[Int]" => Some(data.toInt)
case "Option[Long]" => Some(data.toLong)
case "Option[Double]" => Some(data.toDouble)
}
}
// Isn't this a bad way to solve the problem ?
implicit def anyToInt(str: Any) = str.asInstanceOf[Int]
implicit def anyToLong(str: Any) = str.asInstanceOf[Long]
val i: Int = convertType("1", "Int")
val l: Long = convertType("1", "Long")
保持原始数据类型完好无损的最佳方法是什么?
答案 0 :(得分:0)
import scala.reflect.runtime.universe._
implicit class StringConverter(data: String) {
private[this] def convert(tag: Type): Any = tag match {
case t if t =:= typeOf[Int] => data.toInt
case t if t =:= typeOf[Double] => data.toDouble
case t if t =:= typeOf[Long] => data.toLong
case t if t =:= typeOf[Option[Int]] => Some(data.toInt)
}
def convert[T](implicit typeTag: TypeTag[T]): T = convert(typeTag.tpe).asInstanceOf[T]
}
scala> "123".convert[Int]
res5: Int = 123
scala> "123".convert[Option[Int]]
res6: Option[Int] = Some(123)
scala> "123".convert[Double]
res7: Double = 123.0
正如@Luka Jacobowitz所说,使用generics
转换类型:
implicit TypeTag
使用通用来检索类型信息Type
,案例匹配以解析数据asInstanceOf
将变量转换为目标类型(因为它已经由TypeTag
检查过,这样做是安全的)答案 1 :(得分:0)
你想做的事情有点棘手。正如您所见,子类型不会得到您想要的东西,因为必须返回所有返回类型的超类型。
虽然输入变量,可能会节省一天!
def convertType[T](x: String): T = x.asInstanceOf[T]
但这并不是你想要的......你需要根据T
传递的内容而有不同行为的东西。像(不是真正的Scala)
def convertType[T](x: String): T = T match {
case Double => x.toDouble
case Int => x.toInt
// And all your other cases
}
不幸的是,Scala不是一种完全依赖类型的语言,因此我们没有可以直接对类型起作用的函数,因此匹配语句不起作用。
但是,如果我们为T
类型提供了价值级别的“见证”,那么我们可以放弃转换。
def convertType[T](x: String)(witness: T): T = witness match {
case _: Double => x.toDouble
case _: Int => x.toInt
// Fill in other cases as necessary
}
通过制作见证人implicit
,我们可以让自己稍微方便一点。现在这只会让我们中途停留,因为我们仍然需要有奇怪的虚拟隐含值,除了作为我们函数的见证人之外什么都不做(例如随机我们需要像implicit val z = 2
这样的东西)。 / p>
我们是否可以摆脱创建这些虚拟值以作为证人传递的需要?
是的,有两种方法。一种是使用Scala的TypeTags,它们恰好是编译器自动生成类型的价值级见证。
import scala.reflect.runtime.universe._
def convertTypes[T](x: String)(implicit witness: TypeTag[T]): T = witness match {
case a if a =:= typeOf[Int] => x.toInt
case a if a =:= typeOf[Double] => x.toDouble
}
或者,您可以将实际转换移至单独的特征,并让目击者实施特征指定的行为。
trait Convertable[T] {
def convertFromString(x: String): T
}
implicit object ConvertInt extends Convertable[Int] {
override def convertFromString(x: String): Int = x.toInt
}
// Do the same for your other types
def convertType[T](x: String)(implicit witness: Convertable[T]): T = witness.convertFromString(x)
然后我们去!一个很好的类型安全的转换方法(至少最后一个是)。您可能希望将整个事物包装在scala.util.Try
中,以防您传递格式错误的字符串。
顺便说一下,我们刚刚重新创建了typeclasses(或者使用了Scala的内置TypeTag
类型类。)