scala 私人 [this] 与私人
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9698677/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
private[this] vs private
提问by Soteric
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
在 Scala 中,我看到诸如对象私有变量之类的功能。从我不太丰富的 Java 背景中,我学会了在必要时关闭所有内容(将其设为私有)并打开(提供访问器)。Scala 引入了更严格的访问修饰符。我应该总是默认使用它吗?或者我应该只在某些特定情况下使用它,即使对于同一类的对象,我也需要明确限制更改字段值?换句话说,我应该如何选择
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 hereprivate[this]is just some subcase and instead of thisI can use other modifiers: "package, class or singleton object". So I'll leave it for some special case.
编辑:正如我在这里看到private[this]的只是一些子案例,而不是this我可以使用其他修饰符:“包、类或单例对象”。所以我会把它留给一些特殊情况。
采纳答案by Alexey Romanov
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 privateover protectedover publicdoesn't apply.
我认为这并不重要,因为任何更改都只会影响一个班级。因此,最重要的理由,更喜欢private在protected过public不适。
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 thisproperty is privateand thatone is private[this].
private[this]在性能真正重要的地方使用(因为这样您将获得直接的字段访问而不是方法)。否则,只需选择一种风格,这样人们就不需要弄清楚为什么这个属性是private,那个是private[this]。
回答by denis phillips
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:
有一种情况private[this]需要编译代码。这与方差表示法和可变变量的相互作用有关。考虑以下(无用)类:
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 makeEmptyto clear the value (hence the var). As stated, this is useless except to demonstrate the point.
所以这个类旨在保存一个可选值,将它作为一个选项返回,并使用户能够调用makeEmpty清除该值(因此是 var)。如前所述,除了证明这一点之外,这是无用的。
If you try compiling this code with privateinstead of private[this]it will fail with the following error message:
如果您尝试使用private而不是编译此代码,private[this]则会失败并显示以下错误消息:
error: covariant type T occurs in contravariant position in type Option[T] of value value_= class Holder[+T] (initialValue: Option[T]) {
错误:协变类型 T 出现在值 value_= class Holder[+T] (initialValue: Option[T]) 的类型 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.
发生此错误是因为 value 是协变类型 T (+T) 上的可变变量,这通常是一个问题,除非使用private[this]. 编译器在其方差检查中有特殊处理来处理这种特殊情况。
So it's esoteric but there is a case where private[this]is required over private.
所以它是深奥的,但有一种情况private[this]需要超过private.
回答by comonad
private var nameis accessible from any method of the class Dummy(and its companion object Dummy).
private var name可以从class Dummy(及其伴侣object Dummy)的任何方法访问。
private[this] var nameis accessible from methods of thisobject only, not from other objects of class Dummy.
private[this] var name只能从thisobject 的方法访问,不能从class Dummy.
回答by Pben
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)
private[this](相当于protected[this])意味着“y”只对同一实例中的方法可见。例如,您不能在 equals 方法中的第二个实例上引用 y,即“this.y == that.y”会在“that.y”上生成编译错误。 (来源)
so you can do private[this] every time you want but you can have some problem if you need refer it
所以你可以每次都做私人 [this] 但如果你需要参考它,你可能会遇到一些问题
回答by Marek Adamek
This was tested using scala 2.11.5. Consider the code below
这是使用 Scala 2.11.5 测试的。考虑下面的代码
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
它将像这个 java (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 '[this]' modifier the code below won't compile
但是,如果您使用 '[this]' 修饰符,下面的代码将无法编译
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.
这是因为在第一种情况下 'x' 可以在类级别访问,而在第二种情况下它是更严格的实例级别。这意味着只能从它所属的实例访问“x”。所以 'this.x' 很好,但 'other.x' 不是。
You can refer to section 13.5 of "Programming in Scala: A Comprehensive Step-By-Step Guide" book for more details about access modifiers.
有关访问修饰符的更多详细信息,您可以参考“Scala 编程:综合分步指南”一书的 13.5 节。
回答by Humoyun Ahmad
When adding the scope to the privatemodifier (private[X]), it effectively behaves as a “up to” X, where X designates some enclosing package, class or singleton object.
将作用域添加到私有修饰符 ( private[X]) 时,它实际上表现为“最多”X,其中 X 指定一些封闭的包、类或单例对象。
For example, private[bar], where baris a package means that every instance of every class belonging to package barcan access whichever member the modifier is restricting.
例如,private[bar],其中bar是一个包意味着属于包bar的每个类的每个实例都可以访问修饰符限制的任何成员。
In the case of private[this], it means that the member is only accessible for each instance. This becomes more clear in the following example:
在private[this]的情况下,这意味着该成员只能被每个实例访问。这在以下示例中变得更加清晰:
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 doesn't have any problem since any instance can access the private val i. However for the first Foo there's an error since each instance cannot see other instance's i.
如您所见,第二个 Foo 没有任何问题,因为任何实例都可以访问私有 val i。但是对于第一个 Foo 有一个错误,因为每个实例都看不到其他实例的 i。
It's a good practice to write private[this] since it imposes a bigger restriction.
编写 private[this] 是一个很好的做法,因为它施加了更大的限制。
回答by rafiquenazir
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.
在像 java 这样的大多数 OOP 编程语言中,私有字段/方法意味着这些私有字段/方法不能从类外部访问。但是,同一类的实例/对象可以使用赋值运算符或通过复制构造函数访问对象的私有字段。在 Scala 中,private[this] 是对象私有的,这确保了同一类的任何其他对象都无法访问 private[this] 成员。
Example
例子
1.Without private[this]
1.无私[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]
2.使用私有[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.
因此 private[this] 确保 _password 字段只能通过 this 访问。
回答by DXDXY
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:
为了详细说明 Alexey Romanov 提到的性能问题,以下是我的一些猜测。引自《Scala 编程:全面的分步指南,第 2 版》第 18.2 节:
In Scala, every var that is non-private member of some object implicitly defines a getter and a setter method with it.
在 Scala 中,作为某个对象的非私有成员的每个 var 都隐式地定义了一个 getter 和一个 setter 方法。
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 privatekeyword to variable datawill still cause this compilation error. However, the following code compiles fine:
Scala 抱怨error: ambiguous reference to overloaded definition. 将 override 关键字添加到data_=将无济于事应该证明该方法是由编译器生成的。将private关键字添加到变量data仍然会导致此编译错误。但是,以下代码编译良好:
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.
所以,我想private[this]会阻止 Scala 生成 getter 和 setter 方法。因此,访问此类变量将节省调用 getter 和 setter 方法的开销。
回答by Andriy Kuba
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.
private[this]如果您打算同步变量,最好使用。
Here a good example from the scala style guide of the Spark team:
这是来自Spark 团队的Scala 风格指南的一个很好的例子:
// 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 }
}

