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
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.
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
.
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
.
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]
.
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 }
}
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.