Private [this] versus private

In Scala, I see a function like an object-private variable. From my not-so-rich Java-background, I learned to close everything (make it private) and open (provide access to them), if necessary. Scala introduces an even more restrictive access modifier. Should I always use it by default? Or should I use it only in some specific cases, when I need to explicitly restrict the change in the field value even for objects of the same class? In other words, how to choose

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 good reason?

EDITED: As I see here, private [this] is just some kind of subheading, and instead I can use other modifiers: "package, class or singleton object". Therefore, I will leave this for some special case.

+82
scala
Mar 14 2018-12-12T00:
source share
9 answers

I do not think this is too important, since any changes will affect only one class. Therefore, the most important reason for preferring private over protected over public not applicable.

Use private[this] , where performance really matters (since you will get direct access to fields instead of methods this way). Otherwise, just tune in to one style so people don’t have to figure out why this property is private and the other is private[this] .

+49
Mar 14 '12 at 9:14
source share

There is a case where private[this] is required to compile code. This is due to the interaction of variation notation and variable 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 } } 

Thus, this class is designed to store an optional value, returns it as a parameter, and allows the user to call makeEmpty to clear the value (hence var). As said, this is useless, except to demonstrate meaning.

If you try to compile this code using private instead of private[this] , it will fail with the following error message:

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

This error occurs because the value is a mutable variable in the covariant type T (+ T), which is usually a problem if it is not marked as private for an instance with private[this] . The compiler has special processing in its dispersion to verify this special case.

So this is esoteric, but there is a case where private[this] is required over private .

+91
Mar 15 2018-12-15T00:
source share

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

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

+16
Sep 08 '15 at 8:58
source share

private [this] (equivalent to protected [this]) means that this "y" is only visible to methods in a single instance. For example, you could instead of link y to the second instance using the equal method, that is, "this.y == that.y" generates a compilation error on "that.y". (source)

so that you can do private [this] every time you want, but you may have some kind of problem if you need to refer to it

+11
Mar 14 '12 at 9:14
source share

This has been 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 like this java code (1.8)

 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 the '[this]' modifier, the code below will not 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 available at the class level, while in the second case it is a more strict instance level. This means that "x" can only be obtained from the instance to which it belongs. So, "this.x" is great, but "other.x" is not.

For more information on access modifiers, see Section 13.5, Scala Programming: A Comprehensive Walkthrough.

+9
Mar 11 '15 at 4:23
source share

When adding scope to the modifier private ( private [X] ), it effectively behaves like a β€œbefore” X, where X denotes any encompassing package, class or singleton.

For example, private [bar] , where the bar is a package, means that each instance of each class belonging to the package bar can access which member the modifier modifies.

In the case of private [this], this means that the item is available only for each instance. This becomes clearer in the following example:

 class Foo(foo:Foo){ private[this] val i = 2 println(this.i + foo.i) } >>error: value i is not a member of Foo class Foo(foo:Foo){ private val i = 2 println(this.i + foo.i) } >>defined class Foo 

As you can see, the second Foo has no problem, since any instance can access the private val i. However, there is an error for the first Foo, since each instance cannot see the other i instances.

It’s good practice to write private [this] because it imposes a greater restriction.

+5
Mar 10 '16 at 9:03
source share

To dwell on the performance issue that Alexey Romanov spoke about, here are some of my guesses. Quotes from Scala Programming: A Comprehensive Walkthrough, Second Edition, Section 18.2:

In Scala, every var that is not a private member of an object implicitly defines a getter and setter method.

To verify this, this code will throw a 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 the override keyword to data_= would not help prove that the method is generated by the compiler. Adding the private keyword to the data variable 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 think private[this] prevent the creation of scala generation and setter methods. Thus, access to such a variable will save overhead when calling the getter and setter methods.

+1
Feb 22 '15 at 4:14
source share

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

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

Here is a good example from the scala manual 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 } } 
+1
Jul 14 '16 at 13:29
source share

In most OOP programming languages, such as java, private fields / methods mean that these private fields / methods are not available outside the class. However, instances / objects of the same class can access private fields of objects using the assignment operator or using the copy constructor. In Scala, private [this] is a private object, which ensures that any other object of the same class cannot access private [these] 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. Use of 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 } } 

Therefore, private [this] ensures that the _password field is only available with this.

+1
Apr 26 '17 at 21:36 on
source share



All Articles