138

I have been trying:

class Foo(bar: Int)

vs:

class Foo(private val bar: Int)

and they seem to behave the same although I couldn't find anywhere saying that (bar: Int) expands to (private val bar: Int) so my question is, are these identical/similar?

On a side note, I have been trying to use -Xprint:typer on these code pieces and they produce the same code except for an extra line in the second one. How do I read that extra line?

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

2 Answers 2

187

bar: Int

This is barely a constructor parameter. If this variable is not used anywhere except the constructor, it remains there. No field is generated. Otherwise private val bar field is created and value of bar parameter is assigned to it. No getter is created.

private val bar: Int

Such declaration of parameter will create private val bar field with private getter. This behavior is the same as above no matter if the parameter was used beside the constructor (e.g. in toString() or not).

val bar: Int

Same as above but Scala-like getter is public

bar: Int in case classes

When case classes are involved, by default each parameter has val modifier.

Sign up to request clarification or add additional context in comments.

7 Comments

In case classes all parameters will become "public" val.
@om-nom-nom: sorry, I don't get it. Should I improve formatting/structure to make it more readable?
@TomaszNurkiewicz I'm just a little bit grumpy about letters size ;-) don't take it seriously
@TomaszNurkiewicz: var is available and meaningful to render constructor parameters into (mutable) class properties both in non-case and case classes.
In 'Scala for the Impatient' book written that bar: Int compiled to private[this] val bar: Int
|
116

In the first case, bar is only a constructor parameter. Since the main constructor is the content of the class itself, it is accessible in it, but only from this very instance. So it is almost equivalent to:

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

On the other hand, in the second case bar is a normal private field, so it is accessible to this instance and other instances of Foo. For example, this compiles fine:

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

And runs:

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

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

But this doesn't:

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

1 Comment

this is a better answer than the accepted one; it highlights the difference between bare bar: Int and private val ....

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.