Scala 私人[这]对私人

Scala 私人[这]对私人,scala,Scala,在Scala中,我看到了对象私有变量这样的特性。从我不太丰富的Java背景中,我学会了关闭一切(使其私有化)并在必要时打开(提供访问器)。Scala引入了更严格的访问修饰符。我应该总是默认使用它吗?或者我应该只在某些特定情况下使用它,即使对于同一类的对象,我也需要显式地限制字段值的更改?换句话说,我应该如何在两者之间做出选择 class Dummy { private var name = "default name" } class Dummy { private[this]

在Scala中,我看到了对象私有变量这样的特性。从我不太丰富的Java背景中,我学会了关闭一切(使其私有化)并在必要时打开(提供访问器)。Scala引入了更严格的访问修饰符。我应该总是默认使用它吗?或者我应该只在某些特定情况下使用它,即使对于同一类的对象,我也需要显式地限制字段值的更改?换句话说,我应该如何在两者之间做出选择

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

  }
}