我知道value class
在scala内联编译时的操作.
也许是这样的
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
Run Code Online (Sandbox Code Playgroud)
但这对我来说似乎没什么大不了的.
它可能会提高性能,但是,
打电话this.i + that.i
似乎没有那么慢i + i
为什么我们需要value class
scala和任何用例???
Vic*_*roz 10
让我们看看Scala如何使用值类(-print
选项).
case class A(i: Int) extends AnyVal {
def +(that: A) = A(this.i + that.i)
}
A(1) + A(2)
Run Code Online (Sandbox Code Playgroud)
被翻译成:
final def +$extension($this: Int, that: Int): Int = $this.+(that)
...
A.+$extension(1, 2)
Run Code Online (Sandbox Code Playgroud)
正如你所看到的Scala避免工作带班A
,只是增加了Int
对Int
返回Int
.同时:
case class A(i: Int) {
def +(that: A) = A(this.i + that.i)
}
A(1) + A(2)
Run Code Online (Sandbox Code Playgroud)
被翻译成:
def +(that: A): A = new A(this.i().+(that.i()))
...
new A(1).+(new A(2))
Run Code Online (Sandbox Code Playgroud)
所以要计算1 + 2
你需要实例化A
三次类.
ret*_*hab 10
为什么要将一个值包装到另一个类中?
一个大用例是类型安全.假设你有能够增加金钱的功能,就像这样:
def multiply(factor: Int, amount: Int): Int = ???
Run Code Online (Sandbox Code Playgroud)
这样做的问题是很容易混淆两个参数,因此错误地调用函数.使用值类,您可以创建一个Money
类型并重写函数,如下所示:
case class Money(amount: Int) extends AnyVal
def multiply(factor: Int, amount: Money): Money = ???
Run Code Online (Sandbox Code Playgroud)
现在使用您的特殊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