如何编写函数将字符串转换为泛型类型(Double、Int、Float等)?
下面是我要寻找的功能的伪代码:
def castFromString[A: Manifest](value: String): A = {
if (A == Double) {
parseDouble(value)
} else if (A == Int) {
parseInt(value)
} else {
value.toString()
}
}发布于 2015-06-03 22:50:11
我认为没有一种方法可以用Manifest、ClassTag或TypeTag编写函数,因为它们只能在运行时告诉您类型。要使伪代码函数工作,必须在编译时知道返回类型。
但是,可以通过定义类型类并为希望转换的类型编写实例来实现该函数。下面是一个例子:
import java.lang.Double.parseDouble
import java.lang.Integer.parseInt
trait CastableFromString[A] {
def fromString(string: String): A
}
object CastableFromString {
implicit object DoubleCastableFromString extends CastableFromString[Double] {
override def fromString(string: String): Double =
parseDouble(string)
}
implicit object IntCastableFromString extends CastableFromString[Int] {
override def fromString(string: String): Int =
parseInt(string)
}
implicit object IntListCastableFromString extends CastableFromString[List[Int]] {
override def fromString(string: String): List[Int] =
string.split(',').map(parseInt).toList
}
def castFromString[A](string: String)(implicit cast: CastableFromString[A]): A =
cast.fromString(string)
}
object Main {
import CastableFromString._
def main(args: Array[String]): Unit = {
val d = castFromString[Double]("4.5")
val i = castFromString[Int]("42")
val li = castFromString[List[Int]]("1,2,3")
println(s"d=$d i=$i li=$li")
}
}或者,为了更接近于类似伪代码的东西,您可以使用宏。下面是一个示例(不适用于任何比Scala2.11更早的版本):
import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context
class StringCasterImpl(val c: Context) {
def castFromStringImpl[A: c.WeakTypeTag](string: c.Expr[String]): c.Tree = {
import c.universe._
val t = c.weakTypeOf[A]
if (t =:= typeOf[Double]) {
q"java.lang.Double.parseDouble($string)"
} else if (t =:= typeOf[Int]) {
q"java.lang.Integer.parseInt($string)"
} else if (t =:= typeOf[List[Int]]) {
q"$string.split(',').map(java.lang.Integer.parseInt).toList"
} else {
c.abort(c.enclosingPosition, s"Don't know how to cast $t to String")
}
}
}
object StringCaster {
def castFromString[A](string: String): A =
macro StringCasterImpl.castFromStringImpl[A]
}
// note that this object must be in a separate compilation unit
object Main {
import StringCaster._
def main(args: Array[String]): Unit = {
val d = castFromString[Double]("4.2")
val i = castFromString[Int]("42")
val li = castFromString[List[Int]]("1,2,3")
println(s"d=$d i=$i li=$li")
}
}发布于 2015-06-03 19:46:17
可以定义将字符串转换为特定类型的隐式函数。
然后,当需要时,它将自动铸造。
math.max(1,"3") // throws error但现在
implicit def StringToInt(x: String): Int = x
math.max(1,"3") //>> 3发布于 2015-06-04 13:46:26
如果您想要这样做,可以在runtimeClass中匹配ClassTag。
def castFromString[A: ClassTag](value: String): A = {
val c = implicitly[ClassTag[A]].runtimeClass
if(c == classOf[Double]) parseDouble(value).asInstanceOf[A]
else ...
}注意对asInstanceOf强制转换的需要。@Olli建议的典型方法更安全、更地道。
https://stackoverflow.com/questions/30627573
复制相似问题