Scala相当于Java的Number
我正在为数值域类型构造一个类型层次结构。例如一年是一个Int(它是一个数字),百分比是一个Double,它是一个数字等等。我需要层次结构,以便我可以调用Int或toDouble的值。
但是,原始数字类型的Scala类型层次结构除了AnyVal之外没有共同的祖先。这不包含我需要的{Int,Double}功能。 我可以找到的最接近的类型是Numeric [T],它似乎主要用于某些编译器欺骗。 在Java中,从Number导出的所有数字(包括任意的精度值)。在Scala中如何定义一个接口来满足数字类型的对象? 我现在正在用鸭子打字进行黑客攻击: Any { def toInt: Int def toDouble: Double } 这不仅是长期的,而且导致运行时反映的成本。有更好的吗? 解决方法
数字[T]正是你正在寻找的。 Scala的方式是类型类(即像Numeric这样的东西)。
代替 def foo(x: java.lang.Number) = x.doubleValue 写一个 def foo[T](x: T)(implicit n: Numeric[T]) = n.toDouble(x) def foo[T : Numeric](x: T) = implicitly[Numeric[T]].toDouble(x) 第二个(几乎)只是句法糖。 Numeric.Ops 每当需要操作时,对数字的实例进行调用,当表达式更复杂时,可能会变得笨拙。为了减轻这种情况,Numeric提供了隐式转换mkNumericOps,它用写入数学运算的常用方式(即1 2而不是n.plus(1,2))来增加T. 为了使用这些,只需导入隐式数字的成员: def foo[T](x: T)(implicit n: Numeric[T]) = { import n._ x.toDouble } 注意,由于导入的限制,隐式的缩写语法在这里是不太可取的。 类型类 这里发生了什么?如果参数列表被标记为隐式,则编译器将自动将所需类型的值放在那里,如果在范围中只有一个标记为隐式的值的值存在。如果你写 foo(1.0) 编译器将自动将其更改为 foo(1.0)(Numeric.DoubleIsFractional) 在Double上提供操作的方法foo。 这样做的巨大优点是,您可以在不知道的情况下使类型Numeric。假设你有一个库给你一个类型MyBigInt。现在假设在Java世界 – 不幸的是 – 开发人员没有使它扩展Number。没有什么可以做的 在斯卡拉,你可以写 implicit object MyBigIntIsNumeric extends Numeric[MyBigInt] { def compare(x: MyBigInt,y: MyBigInt) = ... // ... } 并且使用Numeric的所有代码现在都可以与MyBigInt一起工作,但是您不必更改库。所以数字甚至可能是您的项目的私人,这种模式仍然可以工作。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |