gpt4 book ai didi

scala - 如何在没有开销的情况下丰富值(value)类别?

转载 作者:行者123 更新时间:2023-12-03 03:48:12 25 4
gpt4 key购买 nike

Scala 2.10 引入了值类,您可以通过使类扩展 AnyVal 来指定这些值类。值类有很多限制,但它们的巨大优势之一是它们允许扩展方法,而无需创建新类的惩罚:除非需要装箱,例如将值类放入数组中,只需旧类加上一组以该类作为第一个参数的方法即可。因此,

implicit class Foo(val i: Int) extends AnyVal {
def +*(j: Int) = i + j*j
}

解包到的东西不会比你自己编写i + j*j更昂贵(一旦JVM内联方法调用)。

不幸的是,SIP-15 中的限制之一描述值类的是

  1. The underlying type of C may not be a value class.

如果您有一个可以使用的值类,例如,作为提供类型安全单元而无需装箱开销的一种方式(除非您确实需要它):

class Meter(val meters: Double) extends AnyVal {
def centimeters = meters*100.0 // No longer type-safe
def +(m: Meter) = new Meter(meters+m.meters) // Only works with Meter!
}

那么有没有一种方法可以在没有对象创建开销的情况下丰富Meter? SIP-15 中的限制阻止了显而易见的事情

implicit class RichMeter(m: Meter) extends AnyVal { ... }

方法。

最佳答案

为了扩展值类,您需要重新捕获基础类型。由于值类需要使其包装类型可访问(val i 而不仅仅是上面的 i),因此您始终可以这样做。您无法使用方便的隐式类快捷方式,但您仍然可以添加隐式转换。因此,如果您想向 Meter 添加 - 方法,您必须执行类似的操作

class RichMeter(val meters: Double) extends AnyVal {
def -(m: Meter) = new Meter(meters - m.meters)
}
implicit def EnrichMeters(m: Meter) = new RichMeter(m.meters)

另请注意,您可以(自由)用原始值类重新包装任何参数,因此如果它具有您依赖的功能(例如,它包装 Long 但执行复杂的位混合),您可以将底层类重新包装在您想要扩展的值类中,无论您需要什么地方。

(另请注意,除非您导入 language.implicitConversions,否则您会收到警告。)

附录:在 Scala 2.11+ 中,您可以将 val 设为私有(private);对于完成此操作的情况,您将无法使用此技巧。

关于scala - 如何在没有开销的情况下丰富值(value)类别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14861862/

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