2016-11-20 94 views
2

我知道在编译时内嵌在scala中的value class斯卡拉值类,用例

也许这样

case class A(i: Int) extends AnyVal { 
    def +(that: A) = A(this.i + that.i) 
} 
A(1) + A(2) // After compile it equals to 1 + 2 

,但它似乎不是什么大不了的事给我。

它可能提高性能,但是,

调用this.i + that.i不似乎远远低于i + i

为什么我们需要在斯卡拉value class和任何使用情况???

+0

*调用this.i + that.i似乎并不比我慢+ *你是如何确定这一点的?你是否微调了这些代码? –

+0

除了调用更快的事实(无论如何,最可能由JIT编译器内联),值类避免了对象实例化,因此减少了垃圾收集负载。 – Suma

回答

5

为什么要将单个值包装到其他类中?

一个大的用例是类型安全。比方说,你有功能,可以成倍的钱,像这样:

def multiply(factor: Int, amount: Int): Int = ??? 

这里的问题是,这将是很容易混淆的两个参数,因此错误地调用该函数。随着值类,你可以创建一个Money型和重新写入功能,像这样:

case class Money(amount: Int) extends AnyVal 
def multiply(factor: Int, amount: Money): Money = ??? 

现在用你的特殊Money类型,编译器会告诉你,如果你试图传递参数顺序错误。

如果它不是一个价值类,人们可能会说在某些情况下,增加的类型安全性不值得表现惩罚。但是,对于值类,您没有运行时间开销(尽管存在限制:http://docs.scala-lang.org/overviews/core/value-classes.html)。

的替代来达到同样的目的是拆箱(没有运行时开销)标签类型在scalaz:http://eed3si9n.com/learning-scalaz/Tagged+type.html

注意,例如Haskell使用newtype了同样的想法:https://wiki.haskell.org/Newtype

+0

感谢您的帮助。 –

1

Value类是Scala中的一种机制,用于避免分配运行时对象。这是通过定义新的AnyVal子类来完成的。

更多关于值类是这里Value Classes

6

让我们看看Scala中是如何使用值类(-print选项)。

case class A(i: Int) extends AnyVal { 
    def +(that: A) = A(this.i + that.i) 
} 
A(1) + A(2) 

被翻译成:

final def +$extension($this: Int, that: Int): Int = $this.+(that) 
... 
A.+$extension(1, 2) 

正如你所看到的Scala避免与A类工作,只是增加了IntInt返回Int。同时:

case class A(i: Int) { 
    def +(that: A) = A(this.i + that.i) 
} 
A(1) + A(2) 

被翻译成:

def +(that: A): A = new A(this.i().+(that.i())) 
... 
new A(1).+(new A(2)) 

所以计算1 + 2您需要实例类A三次。

+0

多么好的解释!谢谢你的细节。不使用价值类的性能成本似乎很明显 –