private[this] vs private

后端 未结 9 1027
悲哀的现实
悲哀的现实 2020-11-28 01:35

In Scala I see such feature as object-private variable. From my not very rich Java background I learnt to close everything (make it private) and open (provide accessors) if

相关标签:
9条回答
  • 2020-11-28 01:59

    This was tested using scala 2.11.5. Consider the code below

    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
    

    it will compile and work as this java (1.8) code

    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
    

    however if you use '[this]' modifier the code below won't compile

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

    This is because in the first case 'x' is accessible on class level, whereas in the second case is it more strict instance level. It means that 'x' can be accessed only from the instance to which it belongs. So 'this.x' is fine but 'other.x' is not.

    You can refer to section 13.5 of "Programming in Scala: A Comprehensive Step-By-Step Guide" book for more details about access modifiers.

    0 讨论(0)
  • 2020-11-28 02:00

    There is a case where private[this] is required to make code compile. This has to do with an interaction of variance notation and mutable variables. Consider the following (useless) class:

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

    So this class is designed to hold an optional value, return it as an option and enable the user to call makeEmpty to clear the value (hence the var). As stated, this is useless except to demonstrate the point.

    If you try compiling this code with private instead of private[this] it will fail with the following error message:

    error: covariant type T occurs in contravariant position in type Option[T] of value value_= class Holder[+T] (initialValue: Option[T]) {

    This error occurs because value is a mutable variable on the covariant type T (+T) which is normally a problem unless marked as private to the instance with private[this]. The compiler has special handling in its variance checking to handle this special case.

    So it's esoteric but there is a case where private[this] is required over private.

    0 讨论(0)
  • 2020-11-28 02:02

    private var name is accessible from any method of the class Dummy (and its companion object Dummy).

    private[this] var name is accessible from methods of this object only, not from other objects of class Dummy.

    0 讨论(0)
  • 2020-11-28 02:06

    I don't think it matters too much, since any changes will only touch one class either way. So the most important reason to prefer private over protected over public doesn't apply.

    Use private[this] where performance really matters (since you'll get direct field access instead of methods this way). Otherwise, just settle on one style so people don't need to figure out why this property is private and that one is private[this].

    0 讨论(0)
  • 2020-11-28 02:09

    Should I always use it by default? Or should I use it only in some specific cases where I need to explicitly restrict changing field value even for objects of the same class? In other words how should I choose between

    It's better to use private[this] if you plan to synchronize the variable.

    Here a good example from the scala style guide of the Spark team:

    // 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 }
    }
    
    0 讨论(0)
  • 2020-11-28 02:15

    In most OOP programming language like java, private fields/methods mean that these private fields/methods are not accessible outside from the class. However, instances/objects of same class can have access to the private fields of objects using assignment operator or by means of copy constructor. In Scala,private[this] is object private,which makes sure that any other object of same class is unable to access private[this] members.

    Example

    1.Without private[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)
    
    
      }
    }
    

    2.Using private[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
    
      }
    }
    

    Hence private[this] makes sure that _password field is only accessible with this.

    0 讨论(0)
提交回复
热议问题