valor por parametros inicializar defecto scala scala-2.10

por - Scala. ¿Puede una clase de caso con un campo ser una clase de valor?



valor default java (4)

Al menos para "permitir la creación sin nueva sintaxis", puede utilizar métodos u object antiguos con el método de apply . toString tampoco es un problema (si no recuerdo mal), aunque debe definirlo usted mismo si no está utilizando la clase de caso.
Por cierto, el lenguaje permite definir clases de casos que amplían AnyVal , consulte http://docs.scala-lang.org/overviews/core/value-classes.html

Scala 2.10 introdujo clases de valor . Son muy útiles para escribir código de escritura segura. Además, existen algunas limitaciones, algunas de ellas serán detectadas por el compilador y otras requerirán asignación en tiempo de ejecución.

Quiero crear clases de valor utilizando case class sintaxis de la case class , para permitir la creación de una nueva sintaxis y una toString fácil de usar. No hay coincidencia de patrones, ya que requiere asignación.

Entonces la pregunta es: ¿el uso de case class sintaxis de case class requerirá la asignación de la clase de valor?


Consulte la sección de documentación de resumen "Cuando la asignación es necesaria".

Las clases de casos reciben un aviso especial: "Nota: puede usar clases de casos y / o métodos de extensión para una sintaxis más limpia en la práctica".

Pero, como ya dijo @ rudiger-klaehn, el ejemplo de advertencia es proporcionar un AnyVal donde se espera un Any:

package anything // the caveat from the overview trait Distance extends Any case class Meter(val value: Double) extends AnyVal with Distance class Foo { def add(a: Distance, b: Distance): Distance = Meter(2.0) } object Test extends App { val foo = new Foo Console println foo.add(Meter(3.4), Meter(4.3)) }

Mostrando que: javap -app está arreglado en el último 2.11:

scala> :javap -app anything.Test$ public final void delayedEndpoint$anything$Test$1(); flags: ACC_PUBLIC, ACC_FINAL Code: stack=7, locals=1, args_size=1 0: aload_0 1: new #63 // class anything/Foo 4: dup 5: invokespecial #64 // Method anything/Foo."<init>":()V 8: putfield #60 // Field foo:Lanything/Foo; 11: getstatic #69 // Field scala/Console$.MODULE$:Lscala/Console$; 14: aload_0 15: invokevirtual #71 // Method foo:()Lanything/Foo; 18: new #73 // class anything/Meter 21: dup 22: ldc2_w #74 // double 3.4d 25: invokespecial #78 // Method anything/Meter."<init>":(D)V 28: new #73 // class anything/Meter 31: dup 32: ldc2_w #79 // double 4.3d 35: invokespecial #78 // Method anything/Meter."<init>":(D)V 38: invokevirtual #84 // Method anything/Foo.add:(Lanything/Distance;Lanything/Distance;)Lanything/Distance; 41: invokevirtual #88 // Method scala/Console$.println:(Ljava/lang/Object;)V 44: return LocalVariableTable: Start Length Slot Name Signature 0 45 0 this Lanything/Test$; LineNumberTable: line 11: 0 line 12: 11 }

Hay boxeo como nos avisaron.

(Actualización: en realidad, el PR para arreglar -app no ​​se ha fusionado todavía. Manténgase sintonizado).


Para ampliar esta pregunta, Wojciech Langiewicz propone un buen ejemplo de la clase de valor utilizada como clase de caso.

En lugar de:

case class Player(id: Int, gameCash: Int, gameCoins: Int, energy: Int)

Wojciech define:

case class Player(id: PlayerId, gameCash: GameCash, gameCoins: GameCoins, energy: Energy)

con las clases de casos (sin asignación de objetos adicionales en el montón):

case class PlayerId(id: Int) extends AnyVal case class GameCash(value: Int) extends AnyVal case class GameCoins(value: Int) extends AnyVal case class Energy(value: Int) extends AnyVal

Al crear clases de casos que encierran exactamente un parámetro, debe agregar extends AnyVal para permitir que el compilador Scala ejecute más optimizaciones. Básicamente, la comprobación de tipos se realizará solo durante la fase de compilación, pero durante el tiempo de ejecución solo se crearán objetos del tipo subyacente, lo que lleva a menos sobrecarga de memoria .

La adición de tipos personalizados en los puntos específicos de nuestro código no solo mejoró la legibilidad sino que también nos permitió cometer menos errores: descargue algunas de las comprobaciones que de otra manera tendrían que hacerse en las pruebas (o no hacerlo) en el compilador. También puede ver inmediatamente los errores en su IDE o editor.

Debido a que ahora cada componente de la clase Player es en sí mismo un tipo separado, también es muy fácil agregar nuevos operadores que de otra manera probablemente tendrían que agregarse implícitamente, lo que contaminaría un alcance mayor.


Puede tener una clase de caso que es una clase de valor. Como puede ver en el siguiente ejemplo, no hay creación de objetos. Excepto, por supuesto, el inevitable boxeo, si fuera un lanzamiento a Any.

Aquí hay un pedacito de código scala

class ValueClass(val value:Int) extends AnyVal case class ValueCaseClass(value:Int) extends AnyVal class ValueClassTest { var x: ValueClass = new ValueClass(1) var y: ValueCaseClass = ValueCaseClass(2) def m1(x:ValueClass) = x.value def m2(x:ValueCaseClass) = x.value }

Y el bytecode, que no contiene el menor rastro de las dos clases de valor.

Compiled from "ValueClassTest.scala" public class ValueClassTest { public int x(); Code: 0: aload_0 1: getfield #14 // Field x:I 4: ireturn public void x_$eq(int); Code: 0: aload_0 1: iload_1 2: putfield #14 // Field x:I 5: return public int y(); Code: 0: aload_0 1: getfield #21 // Field y:I 4: ireturn public void y_$eq(int); Code: 0: aload_0 1: iload_1 2: putfield #21 // Field y:I 5: return public int m1(int); Code: 0: iload_1 1: ireturn public int m2(int); Code: 0: iload_1 1: ireturn public rklaehn.ValueClassTest(); Code: 0: aload_0 1: invokespecial #29 // Method java/lang/Object."<init>":()V 4: aload_0 5: iconst_1 6: putfield #14 // Field x:I 9: aload_0 10: iconst_2 11: putfield #21 // Field y:I 14: return }