2012-06-30 72 views
8

我想我明白斯卡拉2.10的新的「值類」功能,通過與Haskell的newtype比較:用戶定義的值類在Java中看起來如何?

trait BoundedValue[+This] extends Any { this: This => 

    def upperBound: This 

    def lowerBound: This 

} 

class Probability @throws(classOf[IllegalArgumentException]) (v: Double) extends AnyVal with BoundedValue[Probability] { 

    val value: Double = if ((v >= 0.0) && (v <= 1.0)) v else throw new IllegalArgumentException((v.toString) + "is not within the range [0.0, 1.0]") 

    override val upperBound: Probability = new Probability(0.0) 

    override val lowerBound: Probability = new Probability(1.0) 

    // Implement probability arithmetic here; 
    // will be represented by Double at runtime. 

} 

這個問題我有是,如何值類出現的Java代碼,使用Scala的包在哪裏宣佈?值類是從Java端作爲引用類出現的,還是被完全擦除(並因此顯示爲它所包裝的類型)?換句話說,當Java在源代碼級別上涉及時,類型安全是否是值類?


EDIT

上面的代碼不會編譯,根據SIP-15文件(丹尼爾的回答聯的),因爲值類不允許有任何初始化邏輯,因爲要麼v必須顯式爲val或​​必須有一個unbox方法和相應的box方法對其伴侶對象,並且因爲值類必須只有一個字段。正確的代碼是:

trait BoundedValue[This <: BoundedValue[This]] extends Any { this: This => 

    def upperBound: This 

    def lowerBound: This 

} 

class Probability private[Probability] (value: Double) extends AnyVal with BoundedValue[Probability] { 

    @inline override def upperBound: Probability = new Probability(0.0) 

    @inline override def lowerBound: Probability = new Probability(1.0) 

    @inline def unbox: Double = value 

    // Implement probability arithmetic here; 
    // will be represented by Double at runtime (mostly). 

} 

object Probability { 

    @throws(classOf[IllegalArgumentException]) 
    def box(v: Double): Probability = if ((v >= 0.0) && (v <= 1.0)) new Probability(v) else throw new IllegalArgumentException((v.toString) + "is not within the range [0.0, 1.0]") 

} 

但是,問題本身仍然有效。

+1

在你的測試程序中,你是否能夠將包裝值從Java的有效邊界之外推送出去? –

+0

@DavidHarkness我現在無法使用裝有2.10.0-M4的機器,所以我不知道。我會盡力檢查。 –

回答

6

值類編譯爲普通類,並可能顯示爲引用。

其中的神奇之處在於,當值類不能逃離範圍時,它的所有痕跡都從代碼中刪除,有效地內聯所有代碼。當然,還要提供更多類型的安全性。

另請參閱SIP-15,這解釋了機制。

+0

謝謝!我以爲我讀過SIP,但我想我沒有。 –

+2

一個同樣有趣的問題是,「如何在沒有自身價值類型(例如JVM)的平臺上編碼Scala值類型」是「Scala值類型如何編碼在* *不具有自己的值類型的平臺上CLI)」。例如,Scala是否可以通過編譯爲CLI中的結構來賦值類型?它是否可以保證它們總是被編譯成結構體? –

+1

你的問題非常有趣,但我意識到,不僅CLI支持結構不受支持(它們在SIP中沒有提到,上次我讀它),但它們可能也沒用。值類只能有一個字段,就像Haskell的新類型一樣,因此我認爲使用結構而不是原語不會有幫助。 結構對於內存使用有很多優點 - 但要使用它們,應該提供一個單獨的機制,這是一個請求可以忽略的行爲的註釋。語義問題是結構體應該只能在CLI上而不是在JVM上從AnyVal繼承。 – Blaisorblade

相關問題