8

通过与 Haskell 的比较,我想我了解 Scala 2.10 的新“价值类”功能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,要么Probability必须有一个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]")

}

然而,问题本身仍然有效。

4

1 回答 1

6

值类编译为普通类,很可能作为引用出现。

它们的神奇之处在于,当值类没有逃脱作用域时,它的所有痕迹都会从代码中删除,从而有效地内联所有代码。而且,当然,提供额外的类型安全性。

另见SIP-15,它解释了机制。

于 2012-07-01T03:50:01.633 回答