Scala值类,用例

时间:2016-11-20 13:24:35

标签: scala value-class

我知道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

慢得多

为什么我们在scala和任何用例中需要value class ???

3 个答案:

答案 0 :(得分:9)

为什么要将一个值包装到另一个类中?

一个大用例是类型安全。让我们说你有能够增加金钱的功能,如下:

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

答案 1 :(得分:8)

让我们看看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,只需将Int添加到Int返回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

答案 2 :(得分:1)

  

值类是Scala中的一种机制,可以避免分配运行时对象。这是通过定义新的AnyVal子类来实现的。

有关价值类的更多信息,请访问Value Classes