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.

1
  • 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. Commented Jan 22, 2014 at 17:14

2 Answers 2

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

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

1 Comment

Thanks a lot. I tried to disassemble with 'javap -p PrimaryConstructor' to see private fields and that shows them all.
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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.