gpt4 book ai didi

Scala 等价于 Java 的 Number

转载 作者:行者123 更新时间:2023-12-03 10:22:50 26 4
gpt4 key购买 nike

我正在尝试为数字域类型构建类型层次结构。例如一个 YearInt (这是一个 Number ),一个 PercentageDouble ,这是一个 Number等。我需要层次结构,以便我可以调用 toInttoDouble关于值(value)观。

但是,基本数字类型的 Scala 类型层次结构除了 AnyVal 之外没有共同祖先。 .这不包含 to{Int, Double}我需要的功能。

我能找到的最接近的类型是 Numeric[T] ,这似乎主要是为了一些编译器的诡计而存在的。

在 Java 中,所有来自 Number 的数字(包括任意精度的)。 如何在 Scala 中定义一个满足数字类型对象的接口(interface)?

我目前正在用鸭子打字来破解它:

Any {
def toInt: Int
def toDouble: Double
}

这不仅冗长,而且会产生运行时反射成本。有更好的吗?

最佳答案

Numeric[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 实例的调用每次你需要一个操作的时候可能会变得笨拙,表达式比较复杂。为了缓解这种情况, Numeric提供隐式转换 mkNumericOps增加 T使用编写数学运算的常用方法(即 1 + 2 而不是 n.plus(1,2) )。

为了使用这些,只需导入隐式 Numeric 的成员即可:
def foo[T](x: T)(implicit n: Numeric[T]) = {
import n._
x.toDouble
}

请注意,由于对 import 的限制隐式的缩写语法在这里是不可取的。

类型类

这里会发生什么?如果参数列表被标记为 implicit ,编译器将自动将所需类型的值放在那里,只要该类型的值恰好标记为 implicit存在于范围内。如果你写
foo(1.0)

编译器会自动将其更改为
foo(1.0)(Numeric.DoubleIsFractional)

提供方法 fooDouble 进行操作.

这样做的巨大优势是您可以创建类型 Numeric在他们不知情的情况下。假设你有一个库,它给你一个类型 MyBigInt .现在假设在 Java 世界中 - 不幸的是 - 开发人员没有让它扩展 Number .你无能为力。

在 Scala 中,你可以只写
implicit object MyBigIntIsNumeric extends Numeric[MyBigInt] {
def compare(x: MyBigInt, y: MyBigInt) = ...
// ...
}

以及所有使用 Numeric 的代码现在将与 MyBigInt 一起使用但是 您不必更改库 .所以 Numeric甚至可以是您的项目私有(private)的,并且这种模式仍然有效。

关于Scala 等价于 Java 的 Number,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17999409/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com