Чи параметри конструктора scala за замовчуванням для приватного val?


128

Я намагався:

class Foo(bar: Int)

vs:

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

Відповіді:


177

bar: Int

Це ледь параметр конструктора. Якщо ця змінна не використовується ніде, крім конструктора, вона залишається там. Поле не створюється. В іншому випадку private val barстворюється поле і barйому присвоюється значення параметра. Не створюється жоден геть.

private val bar: Int

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

val bar: Int

Те саме, що вище, але Скала-подібний геттер є загальнодоступним

bar: Int у класах занять

Коли беруть участь класи випадків, за замовчуванням кожен параметр має valмодифікатор.


15
У випадку класів усі параметри стануть "загальнодоступними" val.
drexin

6
Боже, я час від часу ношу окуляри, але це занадто багато.
om-nom-nom

1
@ om-nom-nom: вибач, я не розумію. Чи варто вдосконалити форматування / структуру, щоб зробити його більш читабельним?
Томаш Нуркевич

1
@TomaszNurkiewicz: varдоступний та змістовний для перегляду параметрів конструктора в (змінні) властивості класу як у не-, так caseі у caseкласах.
Рандалл Шульц

8
У книзі "Скала для нетерплячих" написано, що bar: Intскладено наprivate[this] val bar: Int
MyTitle

98

У першому випадку 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 = Foo@7a99d0af

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
  }
}

9
це краща відповідь, ніж прийнята; він підкреслює різницю між голою bar: Intта private val ....
hraban
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.