2

我正在尝试String使用Int提取器。我的代码如下所示。

object Apply {
  def unapply(s: String): Option[Int] = try {
    Some(s.toInt)
  } catch {
    case _: java.lang.Exception => None
  }
}

object App {
  def toT[T](s: AnyRef): Option[T] = s match {
    case v: T => Some(v)
    case _ => None
  }
  def foo(param: String): Int = {
    //reads a Map[String,String] m at runtime
    toT[Int](m("offset")).getOrElse(0)
  }
}

我收到运行时错误:java.lang.String cannot be cast to java.lang.Integer. 似乎根本没有使用提取器。我应该怎么办?

编辑:我的用例如下。我正在使用 play,我想解析在 url 中传递的查询字符串。我想获取查询字符串值(String)并将其用作 Int、Double 等。例如,

val offset = getQueryStringAs[Int]("offset").getOrElse(0)
4

2 回答 2

4

我认为这里最大的问题是,您似乎混淆了转换和转换。您有 a Map[String, String],因此您不能将值转换为Int. 你必须转换它们。幸运的是,ScalatoInt通过对 StringOps 的隐式转换将该方法添加到字符串中。

这应该适合你:

m("offset").toInt

请注意,如果字符串无法转换为整数,toInt则会抛出 a 。java.lang.NumberFormatException

编辑

您想要的将 afaik 仅适用于类型类。

这是一个例子:

trait StringConverter[A] {
  def convert(x: String): A
}

implicit object StringToInt extends StringConverter[Int] {
  def convert(x: String): Int = x.toInt
}

implicit object StringToDouble extends StringConverter[Double] {
  def convert(x: String): Double = x.toDouble
}

implicit def string2StringConversion(x: String) = new {
  def toT[A](implicit ev: StringConverter[A]) = ev.convert(x)
}

用法:

scala> "0.".toT[Double]
res6: Double = 0.0
于 2013-02-09T22:34:40.450 回答
1

您的代码中存在问题,您应该收到编译器警告:

def toT[T](s: AnyRef): Option[T] = s match {
  case v: T => Some(v) // this doesn't work, because T is erased
  case _ => None
}

现在......应该在哪里Apply使用?我看到它声明了,但我没有看到它在任何地方使用。

编辑

关于警告,请查看Stack Overflow 上关于类型擦除的讨论。例如,我写的这个答案是关于如何绕过它——尽管它现在已被 Scala 2.10.0 弃用。

为了解决你的问题,我会使用类型类。例如:

abstract class Converter[T] {
  def convert(s: String): T
}

object Converter {
  def toConverter[T](converter: String => T): Converter[T] = new Converter[T] {
    override def convert(s: String): T = converter(s)
  }

  implicit val intConverter = toConverter(_.toInt)
  implicit val doubleConverter = toConverter(_.toDouble)
}

然后你可以像这样重写你的方法:

val map = Map("offset" -> "10", "price" -> "9.99")

def getQueryStringAs[T : Converter](key: String): Option[T] = {
  val converter = implicitly[Converter[T]]
  try {
    Some(converter convert map(key))
  } catch {
    case ex: Exception => None
  }
}

正在使用:

scala> getQueryStringAs[Int]("offset")
res1: Option[Int] = Some(10)

scala> getQueryStringAs[Double]("price")
res2: Option[Double] = Some(9.99)
于 2013-02-09T22:12:30.507 回答