private[this] vs private

Scala

Scala Problem Overview


In Scala I see such feature as object-private variable. From my not very rich Java background I learnt to close everything (make it private) and open (provide accessors) if necessary. Scala introduces even more strict access modifier. Should I always use it by default? Or should I use it only in some specific cases where I need to explicitly restrict changing field value even for objects of the same class? In other words how should I choose between

class Dummy {
    private var name = "default name"
}

class Dummy {
    private[this] var name = "default name"
}

The second is more strict and I like it but should I always use it or only if I have a strong reason?

EDITED: As I see here private[this] is just some subcase and instead of this I can use other modifiers: "package, class or singleton object". So I'll leave it for some special case.

Scala Solutions


Solution 1 - Scala

There is a case where private[this] is required to make code compile. This has to do with an interaction of variance notation and mutable variables. Consider the following (useless) class:

class Holder[+T] (initialValue: Option[T]) {
    // without [this] it will not compile
    private[this] var value = initialValue

    def getValue = value
    def makeEmpty { value = None }
}

So this class is designed to hold an optional value, return it as an option and enable the user to call makeEmpty to clear the value (hence the var). As stated, this is useless except to demonstrate the point.

If you try compiling this code with private instead of private[this] it will fail with the following error message:

> error: covariant type T occurs in contravariant position in type Option[T] of value value_= class Holder[+T] (initialValue: Option[T]) {

This error occurs because value is a mutable variable on the covariant type T (+T) which is normally a problem unless marked as private to the instance with private[this]. The compiler has special handling in its variance checking to handle this special case.

So it's esoteric but there is a case where private[this] is required over private.

Solution 2 - Scala

I don't think it matters too much, since any changes will only touch one class either way. So the most important reason to prefer private over protected over public doesn't apply.

Use private[this] where performance really matters (since you'll get direct field access instead of methods this way). Otherwise, just settle on one style so people don't need to figure out why this property is private and that one is private[this].

Solution 3 - Scala

private var name is accessible from any method of the class Dummy (and its companion object Dummy).

private[this] var name is accessible from methods of this object only, not from other objects of class Dummy.

Solution 4 - Scala

> private[this] (equivalent to protected[this]) means that that "y" is > only visible to methods in the same instance. For example, you could > not reference y on a second instance in an equals method, i.e., > "this.y == that.y" would generate a compilation error on "that.y". (source)

so you can do private[this] every time you want but you can have some problem if you need refer it

Solution 5 - Scala

This was tested using scala 2.11.5. Consider the code below

class C(private val x: Int) {
  override def equals(obj: Any) = obj match {
    case other: C => x == other.x
    case _ => false
  }
}

println(new C(5) == new C(5)) //true
println(new C(5) == new C(4)) //false

it will compile and work as this java (1.8) code

class C {
    private int x;

    public C(int x) {
        this.x = x;
    }

    public boolean equals(Object obj) {
        if (obj instanceof C) {
            return ((C) obj).x == x;
        }
        else {
            return false;
        }
    }
}

System.out.println(new C(5).equals(new C(5))); //true
System.out.println(new C(5).equals(new C(4))); //false

however if you use '[this]' modifier the code below won't compile

class C(private[this] val x: Int) {
  override def equals(obj: Any) = obj match {
    case other: C => this.x == other.x //problem is here
    case _ => false
  }
}

This is because in the first case 'x' is accessible on class level, whereas in the second case is it more strict instance level. It means that 'x' can be accessed only from the instance to which it belongs. So 'this.x' is fine but 'other.x' is not.

You can refer to section 13.5 of "Programming in Scala: A Comprehensive Step-By-Step Guide" book for more details about access modifiers.

Solution 6 - Scala

In most OOP programming language like java, private fields/methods mean that these private fields/methods are not accessible outside from the class. However, instances/objects of same class can have access to the private fields of objects using assignment operator or by means of copy constructor. In Scala,private[this] is object private,which makes sure that any other object of same class is unable to access private[this] members.

Example

1.Without private[this]

object ObjectPrivateDemo {

  def main(args: Array[String]) {
    var real = new User("realUserName", "realPassword")
    var guest = new User("dummyUserName", "dummyPassword")
    real.displayUser(guest)

  }
}

class User(val username:String,val password:String) {
  private var _username=username
  private var _password=password
  


  def displayUser(guest:User){
  
         println(" guest username="+guest._username+" guest password="+guest._password)
       guest._username= this._username
    guest._password=  this._password
       println(" guest username="+guest._username+" guest password="+guest._password)
    
    
  }
}

2.Using private[this]

class User(val username: String, val password: String) {
  private var _username = username
  private[this] var _password = password

    

  def displayUser(guest: User) {

    println(this._username)
    println(this._password)

    guest._username = this._username
    // for guest._password it will give this :error  value _password is not member of class User
    guest._password = this._password

  }
}

Hence private[this] makes sure that _password field is only accessible with this.

Solution 7 - Scala

To elaborate on the performance issue Alexey Romanov has mentioned, here are some of my guesses. Quotes from book "Programming in Scala: A Comprehensive Step-by-Step Guide, 2nd Edition" Section 18.2: > In Scala, every var that is non-private member of some object implicitly defines a getter and a setter method with it.

To test it out, this code will cause compilation error:

class PrivateTest{
  var data: Int = 0
  def data_=(x : Int){
    require(x > 0)
    data = x
  }
}

Scala complains about error: ambiguous reference to overloaded definition. Adding override keyword to data_= won't help should prove that the method is generated by the compiler. Adding private keyword to variable data will still cause this compilation error. However, the following code compiles fine:

class PrivateTest{
  private[this] var data: Int = 0
  def data_=(x : Int){
    require(x > 0)
    data = x
  }
}

So, I guess private[this] will prevent scala from generating getter and setter methods. Thus, accessing such variable will save the overhead of calling the getter and setter method.

Solution 8 - Scala

> Should I always use it by default? Or should I use it only in some > specific cases where I need to explicitly restrict changing field > value even for objects of the same class? In other words how should I > choose between

It's better to use private[this] if you plan to synchronize the variable.

Here a good example from the scala style guide of the Spark team:

// The following is still unsafe.
class Foo {
  private var count: Int = 0
  def inc(): Unit = synchronized { count += 1 }
}

// The following is safe.
class Foo {
  private[this] var count: Int = 0
  def inc(): Unit = synchronized { count += 1 }
}

Solution 9 - Scala

consider the notation of access_modifier[xxx], it indicates scope of it's target:

package demo.mxl

class PrivateThisDemo(private val aField: String, private[this] val bField: String) {
  def simpleStr: String = s"aField: $aField, bField: $bField"
}

object PrivateThisDemo {
  def main(args: Array[String]): Unit = {
    val obj = new PrivateThisDemo("a", "b")
    println(s"${obj.simpleStr}")
    println(s"${obj.aField}") // compile ok
    println(s"${obj.bField}") // compile error, because here out of 'this' scope
  }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSotericView Question on Stackoverflow
Solution 1 - Scaladenis phillipsView Answer on Stackoverflow
Solution 2 - ScalaAlexey RomanovView Answer on Stackoverflow
Solution 3 - ScalacomonadView Answer on Stackoverflow
Solution 4 - ScalaPbenView Answer on Stackoverflow
Solution 5 - ScalaMarek AdamekView Answer on Stackoverflow
Solution 6 - ScalarafiquenazirView Answer on Stackoverflow
Solution 7 - ScalaDXDXYView Answer on Stackoverflow
Solution 8 - ScalaAndriy KubaView Answer on Stackoverflow
Solution 9 - ScalamashroomView Answer on Stackoverflow