在Any上调用.toDouble并返回选项[Double]

时间:2017-02-08 19:48:41

标签: scala

如果有人对以下内容采取创造性方法,那就很好奇:

def toDouble(any: Any): Option[Double] = // { if any has a .toDouble method call it else return None }

例如,Int,String,Long都有.toDouble方法。如果它存在(甚至非原始类型),我希望它被调用。

理想情况下是这样的(没有.toString先把所有东西都拿出来)

def toDouble(any: Any): Option[Double] = {
  case any.hasToDouble => Try(any.toDouble).toOption
  case _ => None
}

4 个答案:

答案 0 :(得分:4)

您可以使用

def doubleFromAny(in: Any): Option[Double] = {
  Try{in.asInstanceOf[{def toDouble: Double}].toDouble}.toOption
}

这个问题是通过隐式提供的任何toDouble都不起作用(因此字符串"4.5"会给你None)。我也期望表现不会很好。

最后,你需要弄清楚哪些类型是可能的,并使用类似Jon Anderson的答案来检查和演员。

答案 1 :(得分:3)

您可以使用模式匹配。这样做的另一个好处是可以更明确地控制转换的执行方式。 (例如,如果你想尝试额外的字符串解析)

def toDouble(any: Any): Option[Double] = {
  any match {
    case n:Int => Some(n.toDouble)
    case n:Long => Some(n.toDouble)
    case n:Double => Some(n.toDouble)
    case s:String => Try(s.toDouble).toOption
    case _ => None
  }
}

答案 2 :(得分:1)

  def toDouble(a: Any): Option[Double] = try {
    if (a == null) None else {
      Some(a.toString.toDouble)
    }
  } catch {
    case scala.util.control.NonFatal(e) => None
  }

答案 3 :(得分:-1)

其他人提出了很好的答案。我想做的另一种方法是使用隐式对象。对于上面的示例,您可以编写如下内容:

sealed trait ImplicitType[T]
object ImplicitType{
  implicit object IntType extends ImplicitType[Int]
  implicit object StringType extends ImplicitType[String]
  implicit object LongType extends ImplicitType[Long]
  implicit object DoubleType extends ImplicitType[Double]
}

def toDouble[T : ImplicitType](n: T) : Option[Double] = {
  Try(n.toString.toDouble).toOption
}

上述工作原因是,编译器约束来自ImplicitType伴随对象中隐式对象的可用性。上下文绑定隐式def f:ImplicitType [T]默认搜索ImplicitType的伴随对象内的隐式对象。所以现在你可以做以下事情:

val foo = toDouble(1) // Some(1.0)
val foo1 = toDouble("2") //Some(2.0)
val foo2 = toDouble(1L) //Some(1.0)
val foo3 = toDouble("s") //None
val foo4 = toDouble(1.23456e300d) //Some(1.23456E300)

这样,您的toDouble功能根本不会改变。我想不出办法避免toString抱歉。希望这对你有用。