Параметры scala конструктора по умолчанию для private val?

Я пытался:

class Foo(bar: Int)

против

class Foo(private val bar: Int)

и они, похоже, ведут себя одинаково, хотя я не мог найти нигде, говоря, что (bar: Int) расширяется до (private val bar: Int), так что мой вопрос в том, являются ли эти идентичный/подобный?

На стороне примечания, я пытался использовать -Xprint:typer на этих фрагментах кода, и они производят тот же код, за исключением дополнительной строки во втором. Как мне прочитайте эту дополнительную строку?

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

Ответ 1

bar: Int

Это едва ли параметр конструктора. Если эта переменная не используется нигде, кроме конструктора, она остается там. Поле не генерируется. В противном случае создается поле private val bar и ему присваивается значение параметра bar. Создатель не создается.

private val bar: Int

Такое объявление параметра создаст поле private val bar с частным получателем. Это поведение такое же, как и выше, независимо от того, использовался ли параметр рядом с конструктором (например, в toString() или нет).

val bar: Int

То же, что и выше, но Scala -пользователь-получатель является общедоступным

bar: Int в случае классов

При использовании классов case по умолчанию каждый параметр имеет модификатор val.

Ответ 2

В первом случае bar является только параметром конструктора. Поскольку основной конструктор является содержимым самого класса, он доступен в нем, но только из этого самого экземпляра. Таким образом, это почти эквивалентно:

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

С другой стороны, во втором случае bar является обычным частным полем, поэтому он доступен для этого экземпляра и других экземпляров Foo. Например, это компилируется отлично:

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

И запускается:

scala> val a = new Foo(1)
a: Foo = [email protected]

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

Но это не так:

class Foo(bar: Int) {
  def otherBar(f: Foo) {
    println(f.bar) // error! cannot access bar of another foo
  }
}