私人 vs私人

在斯卡拉我看到这样的function作为对象私有variables。 从我不是非常丰富的Java背景中,我学会了closures所有东西(使之成为私有),并在必要时打开(提供访问器)。 Scala引入了更加严格的访问修饰符。 我应该总是默认使用它? 还是应该仅在某些特定情况下使用它,即使是对于同一类的对象,我也需要显式限制更改的字段值? 换句话说,我应该如何select

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

第二个是更严格的,我喜欢它,但我应该总是使用它,或者只有当我有一个强有力的理由?

编辑:正如我在这里看到私人[这]只是一些子情况下,而不是我可以使用其他修饰:“包,类或单身对象”。 所以我会留下一些特殊情况。

我不认为这太重要,因为任何变化只会触及一个类别。 所以selectprivate不是protected public的最重要的原因是不适用的。

在性能真正重要的地方使用private[this] (因为这样可以直接访问字段而不是方法)。 否则,只要定下一种风格,所以人们不需要弄清楚为什么这个属性是private而且private[this]

有一个情况下需要private[this]来编译代码。 这与方差符号和可变variables的相互作用有关。 考虑下面的(无用的)类:

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

所以这个类被devise为保存一个可选的值,作为一个选项返回它,并使用户能够调用makeEmpty清除值(因此var)。 如上所述,除了certificate这一点之外,这是无用的。

如果您尝试使用private而不是private来编译此代码,则会失败,并显示以下错误消息:

错误:协变typesT出现在types为Value的typesOption [T]中的逆变换位置上。class = Holder [+ T](initialValue:Option [T]){

发生此错误是因为值是协变typesT(+ T)上的可变variables,通常这是一个问题,除非标记为私有的private[this]的实例。 编译器在差异检查中有特殊的处理来处理这种特殊情况。

所以它是深奥的,但有一个情况下, private[this]是需要超过private

private var name可以从class Dummy (及其伴随object Dummy )的任何方法访问。

private[this] var name只能从this对象的方法访问,而不能从class Dummy其他对象访问。

private [this](相当于protected [this])意味着“y”只对同一个实例中的方法可见。 例如,你不能在equals方法中的第二个实例上引用y,即“this.y == that.y”会在“that.y”上产生编译错误。 (资源)

所以你可以在每次你想要的时候做私人的事情,但是如果你需要的话可以有一些问题

这是用scala 2.11.5testing的。 考虑下面的代码

 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 

它将编译和工作为这个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 

但是如果你使用'[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 } } 

这是因为在第一种情况下,“x”可以在课堂上进行访问,而在第二种情况下,则是更严格的实例级别。 这意味着“x”只能从它所属的实例访问。 所以'this.x'很好,但'other.x'不是。

有关访问修饰符的更多详细信息,请参阅“Scala编程:详尽的分步指南”一书的第13.5节。

当将范围添加到私有修饰符( private [X] )时,它有效地performance为“最多”X,其中X指定一些封装的包,类或单例对象。

例如, private bar [bar] ,其中bar是一个包,意味着属于包bar的每个类的每个实例都可以访问修饰符限制的成员。

私人情况下,这意味着成员只能在每个实例中访问。 在下面的例子中,这变得更加清楚:

 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 

正如你所看到的,第二个Foo没有任何问题,因为任何实例都可以访问私有的val。 但是对于第一个Foo来说,由于每个实例都看不到其他实例的i,所以出现错误。

写私人书这是一个很好的做法,因为它施加了更大的限制。

为了详细说明Alexey Romanov提到的性能问题,下面是我的一些猜测。 从“Scala编程:综合循序渐进指南,第二版”一书中引用第18.2节:

在Scala中,每个var都是非私有成员,它隐式地定义了一个getter和一个setter方法。

为了testing它,这段代码会导致编译错误:

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

斯卡拉抱怨error: ambiguous reference to overloaded definition 。 将override关键字添加到data_=将无助于certificate该方法是由编译器生成的。 将private关键字添加到variablesdata仍然会导致此编译错误。 但是,下面的代码编译罚款:

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

所以,我猜private[this]会阻止scala生成getter和setter方法。 因此,访问这样的variables将节省调用getter和setter方法的开销。

我应该总是默认使用它? 还是应该仅在某些特定情况下使用它,即使是对于同一类的对象,我也需要显式限制更改的字段值? 换句话说,我应该如何select

如果您打算同步variables,最好使用private[this]

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

在像Java这样的大多数OOP编程语言中,私有字段/方法意味着这些私有字段/方法不能在类之外访问。 但是,相同类的实例/对象可以使用赋值运算符或复制构造函数访问对象的专用字段。 在Scala中,private [this]是私有对象,它确保同一类的任何其他对象不能访问private [this]成员。

1.没有私人的[这个]

 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.使用私人[这个]

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

因此private [this]确保_password字段只能用这个来访问。