2016-11-20 173 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

多麼好的解釋!謝謝你的細節。不使用價值類的性能成本似乎很明顯 –