2009-07-13 15 views
59

En Scala, el constructor primario de una clase no tiene cuerpo explícito, pero se define implícitamente desde el cuerpo de la clase. ¿Cómo, entonces, se puede distinguir entre los campos y los valores locales (es decir, los valores locales del método constructor)?¿Cómo se define un var/val local en el constructor primario en Scala?

Por ejemplo, tomemos el siguiente fragmento de código, una forma modificada de un código de ejemplo de "Programación en Scala":

class R(n: Int, d: Int) { 
    private val g = myfunc 
    val x = n/g 
    val y = d/g 
} 

Mi opinión es que esto va a generar una clase con tres campos: un privado " g ", y público" x "e" y ". Sin embargo, el valor de g se usa solo para el cálculo de los campos xey, y no tiene ningún significado más allá del alcance del constructor.

Entonces, en este ejemplo (ciertamente artificial), ¿cómo se puede definir valores locales para este constructor?

+0

Publicando en caso de que otros tengan una pregunta similar a la mía y hayan venido aquí primero como yo. Si está intentando hacer este mismo concepto pero para _constructors_ use la respuesta a mi pregunta: https://stackoverflow.com/questions/46455835/how-to-define-val-inside-class-constructor-in-scala –

Respuesta

37

E.g.

class R(n: Int, d: Int) { 
    val (x, y) = { 
    val g = myfunc 
    (n/g, d/g) 
    } 
} 
+0

Ah, simple en realidad. Todavía tengo mi intuición sobre el concepto funcional. – skaffman

+47

Esto realmente agregará un campo Tuple2 oculto a su clase. –

+2

Esto puede ser importante. Gracias por el comentario, Jorge. –

16

Existen varias formas de hacerlo. Puede declarar tales variables temporales dentro de definiciones privadas, para usarlas durante el tiempo de construcción. Puede usar variables temporales dentro de bloques que devuelven expresiones (como en la respuesta de Alaz). O, finalmente, puede usar tales variables dentro de constructores alternativos.

De manera similar a los constructores alternativos, también podría definirlos dentro del método "apply" del objeto-compañero.

Lo que no se puede hacer es declarar un campo como "temporal".

Tenga en cuenta también que cualquier parámetro recibido por el constructor primario también es un campo. Si no desea que dichos parámetros se conviertan en campos y no desea exponer los campos reales en un constructor, la solución habitual es hacer privado el constructor primario, con los campos reales, y usar un constructor alternativo o un object-companion's apply() como el constructor "principal" efectivo.

+0

Gracias por la aclaración. – skaffman

6

Algunos discusión sobre este tema, incluyendo los comentarios de Martin Odersky, es here

+0

Ese es el ejemplo exacto del libro que activó mi pregunta :) Supongo que significa que estaba prestando atención ... – skaffman

+0

El hilo se ha eliminado. – ziggystar

+5

Enlace alternativo: http://www.scala-lang.org/node/1198#comment-3430 – robinst

11

Otra opción que tenemos es hacer que el constructor de objetos primaria privada y el uso de un compañero objeto de aplicar el método como constructor. Si aplicamos (juego de palabras no pretende) este enfoque a su ejemplo se vería así:

class R private (val x: Int, val y: Int); 

object R { 
    def apply(n: Int, d: Int): R = { 
    val g = myfunc; 
    new R(n/g, d/g); 
    } 
} 

para crear una instancia de R en lugar de:

val r = new R(1, 2); 

escritura:

val r = R(1, 2); 

Esto es un poco detallado, pero podría ser peor, creo :). Esperemos que los vals privados [este] sean tratados como variables temporales en versiones futuras de Scala. El mismo Martin insinuó eso.

+1

La optimización aún no se implementó a partir de Scala 2.9.0.RC1. – robinst

+0

robinst, incluso en Scala 2.10.2 – MyTitle

Cuestiones relacionadas