加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala相当于Java的Number

发布时间:2020-12-16 09:33:44 所属栏目:安全 来源:网络整理
导读:我正在为数值域类型构造一个类型层次结构。例如一年是一个Int(它是一个数字),百分比是一个Double,它是一个数字等等。我需要层次结构,以便我可以调用Int或toDouble的值。 但是,原始数字类型的Scala类型层次结构除了AnyVal之外没有共同的祖先。这不包含我
我正在为数值域类型构造一个类型层次结构。例如一年是一个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一起工作,但是您不必更改库。所以数字甚至可能是您的项目的私人,这种模式仍然可以工作。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读