在Scala中,我将此特性视为对象私有变量.从我不太丰富的Java背景中,我学会了关闭所有内容(使其成为私有)并在必要时打开(提供访问者).Scala引入了更严格的访问修饰符.我应该总是默认使用它吗?或者我应该只在某些特定情况下使用它,我需要明确限制更改字段值,即使对于同一类的对象?换句话说,我应该如何选择
class Dummy {
private var name = "default name"
}
class Dummy {
private[this] var name = "default name"
}
Run Code Online (Sandbox Code Playgroud)
第二个更严格,我喜欢它,但我应该总是使用它或只有我有充分的理由?
编辑:正如我在这里 看到private[this]的只是一些subcase而不是this我可以使用其他修饰符:"包,类或单例对象".所以我会留下一些特殊情况.
den*_*ips 124
有一种情况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 }
}
Run Code Online (Sandbox Code Playgroud)
因此,此类旨在保存可选值,将其作为选项返回,并允许用户调用makeEmpty以清除值(因此var).如上所述,除了证明这一点之外,这是没用的.
如果您尝试编译此代码private而不是private[this]它将失败,并显示以下错误消息:
错误:协变类型T出现在逆值位置,类型为Option [T],值为value_ = class Holder [+ T](initialValue:Option [T]){
发生此错误是因为value是协变类型T(+ T)上的可变变量,除非将其标记为私有,否则通常会出现问题private[this].编译器在其方差检查中有特殊处理来处理这种特殊情况.
所以这是深奥的,但有一个案例private[this]需要结束private.
Ale*_*nov 59
我认为这不重要,因为任何改变都只会触及一个班级.因此,最重要的理由,更喜欢private在protected过public不适.
private[this]在性能真正重要的地方使用(因为你将以这种方式获得直接的字段访问而不是方法).否则,仅仅满足于一个风格,让人们不用弄清楚为什么这个属性是private和那一个private[this].
com*_*nad 29
private var name可以从class Dummy(和它的同伴object Dummy)的任何方法访问.
private[this] var name只能从this对象的方法访问,而不能从其他对象访问class Dummy.
Mar*_*mek 12
这是使用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
Run Code Online (Sandbox Code Playgroud)
它将编译并作为此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
Run Code Online (Sandbox Code Playgroud)
但是如果你使用'[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
}
}
Run Code Online (Sandbox Code Playgroud)
这是因为在第一种情况下,'x'在类级别上是可访问的,而在第二种情况下,它是更严格的实例级别.这意味着只能从它所属的实例访问"x".所以'this.x'很好,但'other.x'不是.
有关访问修饰符的更多详细信息,请参阅"Scala编程:综合循序渐进指南"一书的第13.5节.
将范围添加到私有修饰符(private [X])时,它实际上表现为"最多"X,其中X表示一些封闭的包,类或单个对象.
例如,private [bar],其中bar是包意味着属于包栏的每个类的每个实例都可以访问修饰符限制的任何成员.
在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
Run Code Online (Sandbox Code Playgroud)
如您所见,第二个Foo没有任何问题,因为任何实例都可以访问私有val i.然而,对于第一个Foo,由于每个实例都看不到其他实例的i,所以会出现错误.
写私有[这]是一个好习惯,因为它会施加更大的限制.
小智 5
在像Java这样的大多数OOP编程语言中,私有字段/方法意味着无法从类外部访问这些私有字段/方法。但是,相同类的实例/对象可以使用赋值运算符或通过复制构造函数访问对象的私有字段。在Scala中,private [this]是私有对象,可确保同一类的任何其他对象都无法访问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)
}
}
Run Code Online (Sandbox Code Playgroud)
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
}
}
Run Code Online (Sandbox Code Playgroud)
因此,private [this]确保_password字段只能通过this进行访问。