¿Los parámetros del constructor de scala están predeterminados en val privado?

128

He estado intentando:

class Foo(bar: Int)

vs:

class Foo(private val bar: Int)

y parecen comportarse de la misma manera, aunque no pude encontrar ningún lugar que diga que se (bar: Int)expande, (private val bar: Int)así que mi pregunta es: ¿son idénticos / similares?

En una nota al margen, he estado tratando de usar -Xprint:typeren estas piezas de código y producen el mismo código, excepto por una línea adicional en la segunda. ¿Cómo leo esa línea extra?

..
class Foo extends scala.AnyRef {
  <paramaccessor> private[this] val bar: Int = _;
  def <init>(bar: Int): this.Foo = {
    Foo.super.<init>();
    ()
  }
}
..


..
class Foo extends scala.AnyRef {
  <paramaccessor> private[this] val bar: Int = _;
  <stable> <accessor> <paramaccessor> private def bar: Int = Foo.this.bar;
  def <init>(bar: Int): this.Foo = {
    Foo.super.<init>();
    ()
  }
}
..
ninguna
fuente

Respuestas:

177

bar: Int

Esto es apenas un parámetro constructor. Si esta variable no se usa en ninguna parte, excepto el constructor, permanece allí. No se genera ningún campo. De lo contrario private val bar, se crea el campo y barse le asigna el valor del parámetro. No se crea getter.

private val bar: Int

Dicha declaración de parámetro creará un private val barcampo con getter privado. Este comportamiento es el mismo que el anterior, sin importar si el parámetro se usó junto al constructor (por ejemplo, dentro toString()o no).

val bar: Int

Igual que el anterior, pero el captador similar a Scala es público

bar: Int en caso de clases

Cuando las clases de casos están involucradas, por defecto cada parámetro tiene un valmodificador.

Tomasz Nurkiewicz
fuente
15
En las clases de caso, todos los parámetros se convertirán en "públicos" val.
drexin
66
Gosh, uso lentes de vez en cuando, pero esto es demasiado.
om-nom-nom
1
@ om-nom-nom: lo siento, no lo entiendo. ¿Debería mejorar el formato / estructura para hacerlo más legible?
Tomasz Nurkiewicz
1
@TomaszNurkiewicz: varestá disponible y es significativo para representar los parámetros del constructor en propiedades de clase (mutables) tanto en clases casecomo no case.
Randall Schulz
8
En 'Scala para impacientes' libro escrito que bar: Intcompila aprivate[this] val bar: Int
MyTitle
98

En el primer caso, bares solo un parámetro constructor. Como el constructor principal es el contenido de la clase en sí, es accesible en él, pero solo desde este mismo caso. Entonces es casi equivalente a:

class Foo(private[this] val bar:Int)

Por otro lado, en el segundo caso bares un campo privado normal , por lo que es accesible para esta instancia y otras instancias de Foo. Por ejemplo, esto compila bien:

class Foo(private val bar: Int) {
  def otherBar(f: Foo) {
    println(f.bar) // access bar of another foo
  }
}

Y corre:

scala> val a = new Foo(1)
a: Foo = Foo@7a99d0af

scala> a.otherBar(new Foo(3))
3

Pero esto no:

class Foo(bar: Int) {
  def otherBar(f: Foo) {
    println(f.bar) // error! cannot access bar of another foo
  }
}
gourlaysama
fuente
9
esta es una mejor respuesta que la aceptada; destaca la diferencia entre desnudo bar: Inty private val ....
hraban