作为参考和对比,首先从Java开始。
在Java中,方法可以访问该类的所有对象的私有字段,例如:
package gao.java;
public class Person {
private String name;
private int age; // 该字段无getter/setter方法
public Person(String name, int age) {
this.name = name;
this.age = age;
}
private String getName() { // 该私有方法只是为了和Scala对比
return name;
}
private void setName(String name) { // 该私有方法只是为了和Scala对比
this.name = name;
}
public boolean equals(Person other) {
return this.name.equals(other.name) && this.age == other.age;
}
}
Person类的equals方法内,能够直接访问其他Person对象的私有字段(other.name/other.age)。
在Scala中,方法也可以访问该类的所有对象的私有字段,成为类私有字段;
但在Scala中,允许定义更加严格的字段访问控制,通过private[this]来实现,称为对象私有字段,即只能在对象内部访问的字段,请看下图:
在图中,job属于类私有字段,salary属于对象私有字段;
方法内不能访问其他对象的对象私有字段(salary)。
Scala编译器分别对private和private[this]都做了什么?
首先对gao.Person.scala文件做一下修改,如下:
package gao
class Person(val name:String, var age:Int) {
private var job = "Programmer"
private[this] var salary = 3000F
}
然后编译该文件,再使用javap查看编译后的Person.class文件,可以看到:
$ javap -p target/scala-2.11/classes/gao/Person.class
Compiled from "Person.scala"
public class gao.Person {
private final java.lang.String name;
private int age;
private java.lang.String job; // private修饰,生成的private的getter/setter方法
private float salary; // private修饰,没有生成getter/setter方法
public java.lang.String name();
public int age();
public void age_$eq(int);
private java.lang.String job(); // job字段的private的getter方法
private void job_$eq(java.lang.String); // job字段的private的setter方法
public gao.Person(java.lang.String, int);
}
这就是Scala编译器private和private[this]对做的工作:
(1)对于类私有的字段,Scala生成私有的getter/setter方法;
(2)对于对象私有的字段,Scala不生成getter/setter方法。