Scala 私人[这]对私人
在Scala中,我看到了对象私有变量这样的特性。从我不太丰富的Java背景中,我学会了关闭一切(使其私有化)并在必要时打开(提供访问器)。Scala引入了更严格的访问修饰符。我应该总是默认使用它吗?或者我应该只在某些特定情况下使用它,即使对于同一类的对象,我也需要显式地限制字段值的更改?换句话说,我应该如何在两者之间做出选择Scala 私人[这]对私人,scala,Scala,在Scala中,我看到了对象私有变量这样的特性。从我不太丰富的Java背景中,我学会了关闭一切(使其私有化)并在必要时打开(提供访问器)。Scala引入了更严格的访问修饰符。我应该总是默认使用它吗?或者我应该只在某些特定情况下使用它,即使对于同一类的对象,我也需要显式地限制字段值的更改?换句话说,我应该如何在两者之间做出选择 class Dummy { private var name = "default name" } class Dummy { private[this]
class Dummy {
private var name = "default name"
}
class Dummy {
private[this] var name = "default name"
}
第二个更严格,我喜欢它,但我应该一直使用它还是只有当我有强烈的理由
编辑:如我所见,
private[this]
只是一些子类,我可以使用其他修饰符来代替this
,“package、class或singleton object”。因此,我将把它留给一些特殊情况。我认为这并不重要,因为任何更改都只会涉及一个类。因此,选择私有
而不是受保护
而不是公共
的最重要原因并不适用
在性能真正重要的地方使用private[this]
(因为这样可以直接访问字段而不是方法)。否则,只需选择一种样式,这样人们就不需要找出为什么此属性是private
,而该属性是private[this]
private[这](相当于protected[这])表示“y”是
仅对同一实例中的方法可见。例如,你可以
在equals方法的第二个实例上不引用y,即。,
“this.y==that.y”将在“that.y”上生成编译错误。
因此,您可以随时执行private[this],但如果需要引用它,您可能会遇到一些问题。在这种情况下,需要使用
private[this]
来编译代码。这与方差表示法和可变变量的相互作用有关。考虑以下(无用)类:
因此,这个类被设计用来保存一个可选值,将其作为选项返回,并允许用户调用makeEmpty
来清除该值(因此是var)。如上所述,这是无用的,除非证明这一点
如果您尝试使用private
而不是private[this]
编译此代码,它将失败并显示以下错误消息:
错误:协变类型T出现在值的类型选项[T]的逆变位置_=
类别持有者[+T](初始值:选项[T]){
发生此错误是因为值是协变类型T(+T)上的可变变量,这通常是一个问题,除非使用private[This]
将实例标记为private。编译器在其方差检查中有特殊处理来处理此特殊情况
因此,这是一个深奥的问题,但有一种情况是,
private[this]
比private
更需要private[this]
来详细阐述Alexey Romanov提到的性能问题,下面是我的一些猜测。
引用《Scala编程:全面分步指南,第二版》第18.2节:
在Scala中,作为某个对象的非私有成员的每个变量都隐式定义了一个getter和一个setter方法
要测试它,此代码将导致编译错误:
class PrivateTest{
var data: Int = 0
def data_=(x : Int){
require(x > 0)
data = x
}
}
Scala抱怨错误:对重载定义的引用不明确。向数据添加override关键字将无助于证明该方法是由编译器生成的。向变量数据添加private
关键字仍将导致此编译错误。但是,以下代码编译es罚款:
class PrivateTest{
private[this] var data: Int = 0
def data_=(x : Int){
require(x > 0)
data = x
}
}
<> P> >我想<代码>私有[这个]/CODE将阻止Scala生成GETER和SETER方法。因此,访问这样的变量将节省调用GETER和SETTER方法的开销。 < P>使用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
它将编译并作为java(1.8)代码工作
但是,如果使用“[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[this]var name
只能从this
对象的方法中访问,不能从类Dummy的其他对象中访问(private[X])将作用域添加到private修饰符(private[X])时,它有效地表现为“最多”X,其中X指定一些封闭的包、类或单例对象
例如,private[bar],其中bar是一个包,这意味着属于packagebar的每个类的每个实例都可以访问修饰符限制的任何成员
在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
正如您所看到的,第二个Foo没有任何问题,因为任何实例都可以访问私有val i。但是对于第一个Foo,有一个错误,因为每个实例都看不到其他实例的i
写私人[这]是一个很好的做法,因为它施加了更大的限制
我应该总是默认使用它吗?还是应该只在某些情况下使用它
我需要明确限制更改字段的特定情况
即使对于同一类的对象也有值?换句话说,我应该怎么做
选择
class Dummy {
private var name = "default name"
}
class Dummy {
private[this] var name = "default name"
}
如果计划同步变量,最好使用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
// 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 }
}
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)
}
}
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
}
}