3

Clarity needed in determining the scope of Scala's constructor parameter

As per this link https://alvinalexander.com/scala/how-to-control-visibility-constructor-fields-scala-val-var-private#comment-13237, whenever a constructor parameter is labelled as private, then no getter and setter methods will be created. But the code I have provided here works fine even though the parameter is labelled as private. I went through this StackOverflow link Do scala constructor parameters default to private val?. This one & the above contradicts. Can someone please explain. The code segment is, in fact, available in the StackOverflow link.

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

The below line runs fine:

val a = new Foo(1)
a.otherBar(new Foo(3))

It prints 3.

As per the first link, the code should result in compile error because the parameter is private.

Salomon Zhang
  • 1,553
  • 3
  • 23
  • 41
user3103957
  • 636
  • 4
  • 16

2 Answers2

3

If you have a look at the scala language specification the private modifier allows access

from within the directly enclosing template and its companion module or companion class.

To allow access only from your inside the instance you can use the modifier private[this]. The code

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

results in

[error] .../src/main/scala/sandbox/Main.scala:9:17: value bar is not a member of sandbox.Foo
[error]       println(f.bar) // access bar of another foo
[error]                 ^
[error] one error found
Harald Gliebe
  • 7,236
  • 3
  • 33
  • 38
  • 1
    Why is `private [this] val bar` better than just `bar`? – Tim May 15 '19 at 13:32
  • If you only use `bar` it is just a constructor parameter, no member variable will be created in class `Foo`. The original poster asked why it was possible to access a `private` member variable from another instance – Harald Gliebe May 15 '19 at 14:32
  • So why is having a member variable better than not having a member variable? Is it something to do with reflection? What other reason is there for creating a member that isn't needed? – Tim May 15 '19 at 14:48
  • If you don't need a member variable, don't use it. I agree with that. But as far as I understood, the original question was about the accessibility rules for a `private` member in Scala. – Harald Gliebe May 15 '19 at 14:54
  • Thanks Harald for you answer! When we say "private val bar: Int" in the constructor parameter (without 'this'), a private field named 'bar' will be created with getter and setter methods. If this is correct,then the link I provided in my question needs to be corrected. – user3103957 May 16 '19 at 04:52
  • @user3103957 Yes, the first answer to the question you linked is not quite correct. A bare constructor parameter does not create a `private val` field, it is just a value that is valid inside the scope of the constructor like any other function parameter. – Tim May 16 '19 at 05:32
3

If you want a constructor parameter that is only visible inside the class, don't make it a member, just make it a normal function parameter:

class Foo(bar: Int) {
  def otherBar(f: Foo) {
    println(f.bar) // Fails: value bar is not a member of Foo
  }
}

All the code inside the constructor can still access bar, but it is not a member of Foo and therefore is not visible outside the constructor.

Tim
  • 26,753
  • 2
  • 16
  • 29