Apakah parameter konstruktor scala default ke val pribadi?

128

Aku sudah mencoba:

class Foo(bar: Int)

vs:

class Foo(private val bar: Int)

dan mereka tampaknya berperilaku sama meskipun saya tidak dapat menemukan di mana pun yang mengatakan bahwa (bar: Int)memperluas (private val bar: Int)pertanyaan saya adalah, apakah ini identik / mirip?

Di samping catatan, saya telah mencoba untuk menggunakan -Xprint:typerpotongan kode ini dan mereka menghasilkan kode yang sama kecuali untuk baris tambahan di yang kedua. Bagaimana saya membaca baris ekstra itu?

..
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>();
    ()
  }
}
..
tidak ada
sumber

Jawaban:

177

bar: Int

Ini bukan parameter konstruktor. Jika variabel ini tidak digunakan di mana pun kecuali konstruktor, itu tetap ada. Tidak ada bidang yang dihasilkan. Jika tidak, private val barbidang dibuat dan nilai barparameter ditetapkan untuknya. Tidak ada pengambil yang dibuat.

private val bar: Int

Deklarasi parameter seperti itu akan membuat private val barbidang dengan pengambil pribadi. Perilaku ini sama seperti di atas tidak peduli apakah parameter digunakan di samping konstruktor (misalnya dalam toString()atau tidak).

val bar: Int

Sama seperti di atas tetapi pengambil Scala seperti ini bersifat publik

bar: Int di kelas kasus

Ketika kelas kasus terlibat, secara default setiap parameter memiliki valpengubah.

Tomasz Nurkiewicz
sumber
15
Dalam kelas kasus semua parameter akan menjadi "publik" val.
drexin
6
Astaga, saya memang memakai kacamata dari waktu ke waktu, tapi ini terlalu berlebihan.
om-nom-nom
1
@ om-nom-nom: maaf, saya tidak mengerti. Haruskah saya memperbaiki pemformatan / struktur agar lebih mudah dibaca?
Tomasz Nurkiewicz
1
@TomaszNurkiewicz: vartersedia dan bermakna untuk merender parameter konstruktor menjadi properti kelas (bisa berubah) baik di kelas non- casemaupun case.
Randall Schulz
8
Dalam buku 'Scala for the Impatient' ditulis yang bar: Intdisusun untukprivate[this] val bar: Int
MyTitle
98

Dalam kasus pertama, barhanya parameter konstruktor. Karena konstruktor utama adalah konten dari kelas itu sendiri, maka dapat diakses di dalamnya, tetapi hanya dari contoh ini saja. Jadi hampir setara dengan:

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

Di sisi lain, dalam kasus kedua baradalah bidang pribadi normal , sehingga dapat diakses ke instance ini dan contoh lain dari Foo. Sebagai contoh, ini mengkompilasi dengan baik:

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

Dan berjalan:

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

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

Tetapi ini tidak:

class Foo(bar: Int) {
  def otherBar(f: Foo) {
    println(f.bar) // error! cannot access bar of another foo
  }
}
gourlaysama
sumber
9
ini adalah jawaban yang lebih baik daripada jawaban yang diterima; itu menyoroti perbedaan antara telanjang bar: Intdan private val ....
hraban