私人[this] vs私人

Sot*_*ric 106 scala

在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.

  • 因为_这个答案是完全错误的_。真正的原因是,正如 Martin Odersky 所说,Scala 的创建者是……这是另一个范围。**私有[this]**,称为对象私有范围,将方法限制为仅适用于该对象。因此,同一类的任何其他实例将无法访问任何**私有[this]**成员。 (2认同)

Ale*_*nov 59

我认为这不重要,因为任何改变都只会触及一个班级.因此,最重要的理由,更喜欢privateprotectedpublic不适.

private[this]在性能真正重要的地方使用(因为你将以这种方式获得直接的字段访问而不是方法).否则,仅仅满足于一个风格,让人们不用弄清楚为什么这个属性是private一个private[this].

  • 请告诉我更多有关表演方面的信息 (55认同)
  • 这个答案有误导性,实际原因是声明网站差异(参见这个答案:http://stackoverflow.com/a/9727849/445715). (9认同)
  • @ om-nom-nom实际上,没什么好说的.JIT应该内联由`private`生成的访问器方法调用,因此影响应为零或至少非常小. (6认同)
  • 嗯.Marek Adamek在下面的回答似乎是选择私人[this]而不是私人的真正原因.目的是限制对特定实例的访问,而不是类的所有实例. (3认同)
  • @AlexeyRomanov - 问题是"我应该总是默认使用它吗?".我想你可以通过说如果你需要来自同一个类的另一个实例的字段的私有[this]来改进你的答案. (3认同)

com*_*nad 29

private var name可以从class Dummy(和它的同伴object Dummy)的任何方法访问.

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


Pbe*_*ben 18

private [this](相当于protected [this])意味着"y"仅对同一实例中的方法可见.例如,您无法在equals方法中引用第二个实例上的y,即"this.y == that.y"会在"that.y"上生成编译错误. (资源)

所以你可以在你想要的时候私下[这个],但如果你需要参考,你会遇到一些问题

  • `private [this]`不等于`protected [this]`.`protected [this]`允许子类实例访问该成员. (13认同)

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节.


Hum*_*mad 8

将范围添加到私有修饰符(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进行访问。

  • 这是迄今为止最清晰、最客观的答案。 (2认同)