2012-06-30 27 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

相关问题