2

I am having hard time to understand the concept of primary constructor and it's parameters. What I have understood till now is: if we define a class as following

class Example(a: Int, b: Int)

Scala compiler generates a primary constructor of the class Examples with the above two parameters. But, it doesn't defines fields a and b in the class Example's definition. But if we define

class Example(val a: Int, val b: Int)

scala compiler generates the primary constructor as above and adds two fields in the class definition.

Now the problem comes when I am trying an example like

class PrimaryConstructor(a: Int, b: Int){
    override def toString() = "PrimaryConstructor(" + this.a + ", " + this.b + ")"
}

The above code compiles well even if there is no fields named either a or b. I am not able to understand that if there are no any fields as such then how I am able to access them using this: the current object reference.

object Main{
    def main(args: Array[String]){
            val primaryConstructor = new PrimaryConstructor(1, 2)
            println(primaryConstructor.a)
    }
}

While if I try to access them from out side the class definition as above, I get the following error message after compilation.

error: value a is not a member of PrimaryConstructor
    println(primaryConstructor.a)

I can understand this. But, how can I access those fields using this? Please help me to understand this.

giampaolo
  • 6,906
  • 5
  • 45
  • 73
Vaibhav Raj
  • 2,214
  • 4
  • 23
  • 39
  • 1
    If you have some Javascript experience, try abandoning the Java notion of a class and instead think of a class as closure (function) over the parameters in the primary constructor. The notion of "everything as a closure" is a core concept of scala which is very powerful once you grok it. A primary constructor ensures that there is a single canonical representation of state to which a class associates behavior. – J Cracknell Jan 22 '14 at 17:14

2 Answers2

3

It basically generates a private val, so

class A(a:Int) {
    def func = a
}

and

class A(private[this] val a:Int) {
    def func = a
}

are equivalent. This may not be entirely true if you omit the function.

When a constructor parameter is referred outside the constructor body ( such as in example func above ), Scala generates a private[this] val, otherwise not.

You can check scala spec for more details or look at this stackoverflow question

Community
  • 1
  • 1
Martin Kolinek
  • 2,010
  • 14
  • 16
  • Thanks a lot. I tried to disassemble with 'javap -p PrimaryConstructor' to see private fields and that shows them all. – Vaibhav Raj Jan 23 '14 at 11:07
2

Martin's answer is great:

It basically generates a private val, so

class A(a:Int) {
  def func = a
}

and

class A(private[this] val a:Int) {
  def func = a
}

are equivalent and you can access a from inside your class.

But, note that class A(a: Int) means that the field a is instance private. Meaning that you cannot write something like this:

class A(a: Int){
  def sum(other: A): Int = {
    this.a + other.a
  }
}

other.a is not allowed even though both instances are of the same type. You can only use this.a.

vptheron
  • 7,426
  • 25
  • 34