本文讨论一下在Scala语言里,字段(Fields)是如何实现的
字段实际上是getter/setter方法
在Scala里,字段是通过var或val关键字来定义的。var字段是可读写的,val字段是只读的。下面是一个简单的例子:
class MyObj {
var intVar = 1
val strVal = "str"
}
反编译之后,可以得到下面的Java代码:
public class MyObj {
private int intVar = 1;
private final String strVal = "str";
public int intVar() {return intVar;}
public void intVar_$eq(int intVar) {this.intVar = intVar;}
public String strVal() {return strVal;}
}
可见:
- 对于var字段,Scala编译器会生成相应的Java字段和一对儿getter/setter方法
- 对于val字段,编译器会生成final字段和getter方法
- getter方法和字段同名
- setter方法为:字段名_$eq
抽象字段
因为字段实际上就是getter/setter方法,所以在Scala里,可以定义抽象字段(只要不赋初始值即可):
abstract class AbstractObj {
var intVar: Int
val strVal: String
}
反编译之后,得到下面Java代码:
public abstract class AbstractObj {
public abstract int intVar();
public abstract void intVar_$eq(int intVar);
public abstract String strVal();
}
字段重写
只有val字段可以被override,如下所示:
class MySubObj extends MyObj {
override val strVal = "substr"
}
反编译后,得到下面的Java代码:
public class MySubObj extends MyObj {
private final String strVal = "substr";
@Override
public String strVal() {
return strVal;
}
}
如果不想让val字段被子类重写,可以给字段加上
final关键字:
class MyObj {
var intVar = 1
final val strVal = "str"
}
private字段
字段默认是public,但是即使改成private,Scala仍然会给字段生成getter/setter方法。如果字段只在对象内使用,可以把字段的访问级别设置成private[this],这样,字段的含义就跟Java一样了(而且拥有更小的可见范围--只有对象自己可见):
class ObjectPrivateFields {
private[this] var intVar = 1
private[this] val strVal = "str"
}
生成JavaBean风格Getter/Setter方法
如果想生成JavaBean风格的getter/setter方法,可以给字段打上@BeanProperty注解:
import scala.beans.BeanProperty
class ScalaBean {
@BeanProperty var intVar = 1
@BeanProperty val strVal = "str"
}
参考资料
《Scala for the Impatient》