Scala类的属性
Scala类最简单的形式看上去和Java或C++中的很相似:
class Demo1 {
private var value = 0 // 必须初始化字段
def increment(): Unit = { // 方法默认是共有的
value += 1
}
// def current(): Int = value
def current: Int = value
}
调用无参方法(比如current时,可以写上圆括号,也可以写;?一般认为对于改值器方法(即改变对象状态的方法)使用(),而对于取值器方法(不会改变对象状态的方法)去掉()是不错的风格;可以通过以不带()的方式 current来强这种风格。
Scala对每个字段都提供了类似于getter和setter的方法,如下:
class Demo2 {
// 必须初始化字段
private var value1 = 0
var value2 = 0
val value3 = 0
private[this] var value4 = 0
}
编译后的class文件:
public class Demo2
{
private void value1_$eq(int x$1)
{
this.value1 = x$1;
}
private int value1()
{
return this.value1;
}
private int value1 = 0;
public void value2_$eq(int x$1)
{
this.value2 = x$1;
}
public int value2()
{
return this.value2;
}
private int value2 = 0;
public int value3()
{
return this.value3;
}
private final int value3 = 0;
private int value4 = 0;
}
可以发现:
- 如果属性是private修饰,则getter和setter方法也是私有的。
- 如果属性是val修饰,则只有getter方法被生成;只读属性,有getter没有setter,属性的值在对象构建完成后就不在改变。不过也可以使用Demo1的方式修改。
- 如果不需要getter和setter方法,可以将属性声明为private[this]。
在scala中,方法可以访问该类的所有对象的私有字段。例如:
class Demo3 {
private var value = 0
def increment(): Unit = {
value += 1
}
def isLess(other: Demo3): Boolean = value < other.value
}
之所以访问other.value
是合法的,是因为other也同样是Demo3对象。
Scala允许我们定义更加严格的访问限制,通过private[this]
这个修饰符来实现。例如:
class Demo3 {
/**
* 这样一来, Demo3的方法只能访问到当前对象的value字段,而不能访问同样是Demo3型的其他对象的该宇段;这样的访问有时被称为对象私有的。
*/
private[this] var value = 0
def increment(): Unit = {
value += 1
}
// def isLess(other: Demo3): Boolean = value < other.value 会报错
}
对于类私有的属性, Scala生成私有的getter和setter方法;但对于对象私有的属性,Scala根本不会生成getter和setter方法。
Scala对于你定义的字段提供了getter和setter方法;不过 ,这些方法的名称并不是Java工具所预期的;许多Java工具都依赖这样的命名习惯。当你将Scala属性标注为@BeanProperty
时,这样的方法会自动生成。例如:
import scala.beans.BeanProperty
class Demo4 {
@BeanProperty var value: String = _
}
编译后的class文件:
public class Demo4
{
private String value;
public String getValue()
{
return value();
}
public void setValue(String x$1)
{
this.value = x$1;
}
public void value_$eq(String x$1)
{
this.value = x$1;
}
public String value()
{
return this.value;
}
}
总结
字段生成的方式:
Scala字段 | 生成的方法 | 何时使用 |
---|---|---|
val / var name | 公有的name name_ = (仅限于var) | 实现一个可以被公开访问并且背后是以字段形式保存的属性 |
@BeanProperty val / var name | 公有的name getName() name_ = (仅限于var) setName(…) (仅限于var) | 与JavaBeans互操作 |
private val / var name | 私有的name name_ = (仅限于var) | 用于将属性访问限制在本类的方法,就和Java一样。尽量使用private,除非你真的需要公有的属性 |
private[this] val / var name | 无 | 用于将字段访问限制在同一个对象上调用的方法 |
private[类名] val / var name | 依赖于具体实现 | 将访问权赋予外部类 |
参考:快学scala(第二版)