2012-06-30 5 views
8

私はHaskellのnewtypeと比較して、Scalaの2.10の新しい「値クラス」機能を理解すると思う:ユーザー定義の値クラスは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. 

} 

私が持っている問題は、値クラスはScalaのパッケージを使用するJavaコードに表示されないか、ありますそれは宣言されていますか?値クラスは、Java側からの参照クラスとして表示されるか、完全に消去される(したがって、ラップする型として表示されます)か?言い換えれば、Javaがソースレベルに関与しているときの型セーフはどのように値クラスですか?


値クラスは、任意の初期化ロジックを持つことが許されないため、上記のコードは、(ダニエルの答えにリンク)SIP-15文書によれば、コンパイルされません

EDIT、なぜならvは明示的にvalでなければならず、​​はunboxメソッドとそれに対応するboxメソッドを持つ必要があります。また、値クラスには正確に1つのフィールドが必要です。正しいコードは次のとおりです。

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の値型はどのようにして"と "まったく興味深い質問です。 CLI)」を選択します。たとえば、CLIでstructにコンパイルしてScalaの値の型を指定できますか?常にstructsにコンパイルされることが保証されていますか? –

+1

あなたの質問は非常に興味深いですが、私はCLIの構造体がサポートされていないだけでなく(彼らがSIPで言及されていない、最後に私が読んでいた) Valueクラスは、Haskellのnewtypeのように、単一のフィールドしか持てないので、プリミティブではなく構造体を使うといいでしょう。 構造体にはメモリ使用に多くの利点がありますが、それらを使用するには、別個のメカニズムを提供する必要があります。つまり、この動作を要求するアノテーションは無視できます。意味上の問題は、構造体がJVM上ではなく、CLI上でのみAnyValから継承されるべきであるということです。 – Blaisorblade