Verwenden die Scala-Konstruktorparameter standardmäßig den privaten Wert?

128

Ich habe es versucht:

class Foo(bar: Int)

vs:

class Foo(private val bar: Int)

und sie scheinen sich gleich zu verhalten, obwohl ich nirgendwo etwas finden konnte, das sich (bar: Int)erweitert, (private val bar: Int)so dass meine Frage lautet: Sind diese identisch / ähnlich?

Nebenbei bemerkt, ich habe versucht, -Xprint:typerdiese Codeteile zu verwenden, und sie erzeugen denselben Code, mit Ausnahme einer zusätzlichen Zeile in der zweiten. Wie lese ich diese zusätzliche Zeile?

..
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>();
    ()
  }
}
..
keiner
quelle

Antworten:

177

bar: Int

Dies ist kaum ein Konstruktorparameter. Wenn diese Variable nur im Konstruktor verwendet wird, bleibt sie dort. Es wird kein Feld generiert. Andernfalls wird ein private val barFeld erstellt und dem barParameter ein Wert zugewiesen. Es wird kein Getter erstellt.

private val bar: Int

Eine solche Parameterdeklaration erzeugt ein private val barFeld mit einem privaten Getter. Dieses Verhalten ist das gleiche wie oben, unabhängig davon, ob der Parameter neben dem Konstruktor verwendet wurde (z. B. in toString()oder nicht).

val bar: Int

Wie oben, aber Scala-ähnlicher Getter ist öffentlich

bar: Int in Klassen

Wenn Fallklassen beteiligt sind, hat standardmäßig jeder Parameter einen valModifikator.

Tomasz Nurkiewicz
quelle
15
In Klassen werden alle Parameter "öffentlich" val.
Drexin
6
Meine Güte, ich trage von Zeit zu Zeit eine Brille, aber das ist zu viel.
Om-Nom-Nom
1
@ om-nom-nom: Entschuldigung, ich verstehe es nicht. Sollte ich die Formatierung / Struktur verbessern, um sie besser lesbar zu machen?
Tomasz Nurkiewicz
1
@TomaszNurkiewicz: varist verfügbar und sinnvoll, um Konstruktorparameter in (veränderbare) Klasseneigenschaften sowohl in Nicht- caseals auch in caseKlassen zu rendern .
Randall Schulz
8
In 'Scala for the Impatient' Buch geschrieben, das bar: Intzusammengestellt zuprivate[this] val bar: Int
MyTitle
98

Im ersten Fall barhandelt es sich nur um einen Konstruktorparameter. Da der Hauptkonstruktor der Inhalt der Klasse selbst ist, kann darauf zugegriffen werden, jedoch nur von dieser Instanz aus. Es ist also fast gleichbedeutend mit:

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

Auf der anderen Seite handelt es sich im zweiten Fall barum ein normales privates Feld, auf das diese Instanz und andere Instanzen von zugreifen können Foo. Zum Beispiel kompiliert dies gut:

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

Und läuft:

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

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

Das geht aber nicht:

class Foo(bar: Int) {
  def otherBar(f: Foo) {
    println(f.bar) // error! cannot access bar of another foo
  }
}
Gourlaysama
quelle
9
Dies ist eine bessere Antwort als die akzeptierte. es hebt den Unterschied zwischen nackt bar: Intund private val ....
Hraban