8

Haskell のnewtype:

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 ドキュメント (Daniel の回答にリンクされています) によると、上記のコードはコンパイルされません。値クラスは初期化ロジックを持つことが許可されていないためですv。明示的に val であるかProbabilityunboxメソッドと対応する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]")

}

ただし、質問自体はそのまま有効です。

4

1 に答える 1

6

値クラスは通常のクラスとしてコンパイルされ、参照として表示される可能性があります。

それらの魔法は、値クラスがスコープをエスケープしない場合、そのすべての痕跡がコードから消去され、すべてのコードが効果的にインライン化されることです。そしてもちろん、追加の型安全性を提供します。

メカニズムを説明しているSIP-15も参照してください。

于 2012-07-01T03:50:01.633 に答える