Les paramètres du constructeur scala sont-ils par défaut val privés?

128

J'ai essayé:

class Foo(bar: Int)

contre:

class Foo(private val bar: Int)

et ils semblent se comporter de la même manière bien que je ne puisse trouver nulle part disant que cela se (bar: Int)développe (private val bar: Int)donc ma question est, sont-ils identiques / similaires?

Sur une note latérale, j'ai essayé d'utiliser -Xprint:typersur ces morceaux de code et ils produisent le même code à l'exception d'une ligne supplémentaire dans le second. Comment lire cette ligne supplémentaire?

..
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>();
    ()
  }
}
..
aucun
la source

Réponses:

177

bar: Int

C'est à peine un paramètre de constructeur. Si cette variable n'est utilisée nulle part sauf le constructeur, elle y reste. Aucun champ n'est généré. Sinon, le private val barchamp est créé et la valeur du barparamètre lui est affectée. Aucun getter n'est créé.

private val bar: Int

Une telle déclaration de paramètre créera un private val barchamp avec un getter privé. Ce comportement est le même que ci-dessus, peu importe si le paramètre a été utilisé à côté du constructeur (par exemple, in toString()ou non).

val bar: Int

Idem que ci-dessus mais le getter de type Scala est public

bar: Int dans les classes de cas

Lorsque des classes de cas sont impliquées, par défaut, chaque paramètre a un valmodificateur.

Tomasz Nurkiewicz
la source
15
Dans le cas des classes, tous les paramètres deviendront "publics" val.
drexin
6
Gosh, je porte des lunettes de temps en temps, mais c'est trop.
om-nom-nom
1
@ om-nom-nom: désolé, je ne comprends pas. Dois-je améliorer le formatage / la structure pour le rendre plus lisible?
Tomasz Nurkiewicz
1
@TomaszNurkiewicz: varest disponible et utile pour rendre les paramètres du constructeur en propriétés de classe (mutables) à la fois dans les classes non caseet case.
Randall Schulz
8
Dans le livre 'Scala for the Impatient' écrit qui bar: Intcompilé àprivate[this] val bar: Int
MyTitle
98

Dans le premier cas, barn'est qu'un paramètre de constructeur. Puisque le constructeur principal est le contenu de la classe elle-même, il y est accessible, mais uniquement à partir de cette instance. Donc c'est presque équivalent à:

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

D'autre part, dans le second cas, il bars'agit d'un champ privé normal , il est donc accessible à cette instance et à d' autres instances de Foo. Par exemple, cela compile bien:

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

Et s'exécute:

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

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

Mais cela ne:

class Foo(bar: Int) {
  def otherBar(f: Foo) {
    println(f.bar) // error! cannot access bar of another foo
  }
}
gourlaysama
la source
9
c'est une meilleure réponse que celle acceptée; il met en évidence la différence entre bare bar: Intet private val ....
hraban