我认为我能通过与Haskell的newtype
进行比较来理解Scala 2.10中新的“value class”功能:
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]")
}
这个问题本身仍然有效,不过需要注意的是。