2012-06-30 20 views
8

Creo que comprendo la nueva característica de "clase de valor" de Scala 2,10, en comparación con newtype de Haskell:¿A qué se parecen las clases de valores definidas por el usuario de 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. 

} 

La pregunta que tengo es, ¿Por qué aparece una clase de valor de código Java que utiliza el paquete Scala en que se declara? ¿La clase de valor aparece como una clase de referencia del lado de Java, o se borra por completo (y, por lo tanto, aparece como el tipo que envuelve)? En otras palabras, ¿qué tipo de seguridad tienen las clases de valor cuando Java está involucrado en el nivel de origen?


EDITAR

El código anterior no se compilará, de acuerdo con el documento SIP-15 (vinculado en la respuesta de Daniel), porque las clases de valor no se les permite tener cualquier lógica de inicialización, porque ya sea v debe ser explícitamente un val o Probability debe tener un método y una unboxbox método correspondiente en él es objeto acompañante, y porque las clases de valor deben tener exactamente un campo. El código correcto es:

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]") 

} 

La pregunta en sí sigue siendo válida, sin embargo.

+1

En su programa de pruebas, que fueron capaces de empujar el valor envuelta fuera de los límites válidos de Java? –

+0

@DavidHarkness No tengo acceso a una máquina con 2.10.0-M4 en este momento, así que no sé. Comprobaré cuando pueda. –

Respuesta

6

clases de valores compilan como clases normales, y también pueden aparecer como referencias.

La magia en ellos es que, cuando la clase valor no escapa del alcance, todo rastro de ella se borran de código, inlining efectivamente todo el código. Y, por supuesto, dando seguridad de tipo adicional.

Ver también SIP-15, lo que explica la mecánica.

+0

¡Gracias! Pensé que había leído el SIP, pero creo que no. –

+2

una pregunta igualmente interesantes como "¿cómo están los tipos de valor Scala codificados en una plataforma que no lleve a cabo (por ejemplo, JVM) los tipos de valor" es "cómo se codifican los tipos de valor Scala en una plataforma que * no * tiene en sí los tipos de valor (por ejemplo, CLI) ". Por ejemplo, ¿se pueden compilar los tipos de valores de Scala en estructuras en la CLI? ¿Está garantizado que * siempre * se compilará en las estructuras? –

+1

Su pregunta es muy interesante, pero me di cuenta de que no solo las estructuras CLI no son compatibles (no se mencionaron en el SIP, la última vez que lo leí), sino que probablemente también sean inútiles. Las clases de valor solo pueden tener un solo campo, como los nuevos tipos de Haskell, por lo tanto, creo que usar estructuras y no primitivas no ayudaría. Las estructuras tienen muchas ventajas para el uso de la memoria, pero para usarlas, se debe proporcionar un mecanismo separado, es decir, una anotación que solicite este comportamiento que puede ignorarse. El problema semántico es que las estructuras probablemente heredarán de AnyVal solo en la CLI, no en la JVM. – Blaisorblade

Cuestiones relacionadas