一个简单的Scala类:
当然还可以更简单的定义这个Person类:
如果不想由Scala生成getter和setter方法呢?
关于构造函数
如果喜欢传统的JavaBean风格的getter与setter,可以这样:
class Person {
private var name: String = _
private var age = 0
def this(name: String, age: Int) { //实际上this是重载了主构造器,使用new Person()依然可以创建对象
this //默认构造器,即主构造器,class Person实际上省略了(),class Person()是主构造器
this.name = name
this.age = age
}
def getName() = name //或则def getName = name
def setName(name: String) { this.name = name }
}
object ClassTest {
def main(args: Array[String]): Unit = {
val a = new Person()
println(a.getName())
val b = new Person("zero", 18)
println(b.getName())
}
}运行结果:null
zero如注释,this方法是重载了主构造器,使用new Person()依然可以创建对象,在this方法中必须先调用this默认构造器,即主构造器,class Person实际上省略了(),class Person()是主构造器。和Java不一样,这里new Person()依然可以创建对象,如果想禁掉这种创建类的方式可以这样:class Person private () {
private var name: String = _
private var age = 0
def this(name: String, age: Int) {
this
this.name = name
this.age = age
}
def getName() = this.name
def setName(name: String) { this.name = name }
}需要注意的是,在这种方式下定义类成员时必须要显式的指明初始值当然还可以更简单的定义这个Person类:
class Person(val name: String, var age: Int, gender: String, number: Int) {
def getNumber() = this.number;
}
object ClassTest {
def main(args: Array[String]): Unit = {
val b = new Person("zero", 18, "男", 7)
b.age_=(20)
println(b.name)
println(b.age)
}
}使用jd-gui-windows-1.4.0(一下简称jd-gui)反编译Person.class后的结果如下:public class Person{
private final String name;
public String name(){
return this.name;
}
public int age(){
return this.age;
}
public void age_$eq(int x$1){
this.age = x$1;
}
public int getNumber(){
return this.number;
}
public Person(String name, int age, String gender, int number) {}
}再使用javap –private Person.class反编译结果如下:public class com.zero.clazz.Person {
private final java.lang.String name;
private int age;
private final int number;
public java.lang.String name();
public int age();
public void age_$eq(int);
public int getNumber();
public com.zero.clazz.Person(java.lang.String, int, java.lang.String, int);
}结合两个工具的反编译结果分析:Scala自动将这个类变成了public,在Scala中任何没有标记为private或则protected的数据都默认为public。Scala将声明为var的age成员用private修饰,并对外提供getter和setter方法用以取值和赋值(在Scala中,getter和setter分别叫做age和age_=,默认的getter和setter是由Scala自动生成),将声明为val的成员用private final修饰,并对外提供getter方法用以取值。对于既不是var也不是val的成员,如果在类中没有被使用,那么就忽略了该字段,如果被使用了(只能够取值不能赋值),那个该字段就晋升为类的成员,被private
final修饰。如果不想由Scala生成getter和setter方法呢?
class Person(val name: String) {
private var age = 0
private[this] var gender: String = "男"
}javap反编译结果:public class com.zero.clazz.Person {
private final java.lang.String name;
private int age;
private java.lang.String gender;
public java.lang.String name();
private int age();
private void age_$eq(int);
public com.zero.clazz.Person(java.lang.String);
}可以发现,private [this] var gender类似于定义对象的私有字段,其他同一个类的对象也无法访问到,Scala不会生成getter或setter方法。关于构造函数
class Person(val name: String, var age: Int, gender: String) {
private var firstName: String = _
def this(name: String, age: Int, gender: String, firstName: String) {
this(name, age, gender)
this.firstName = firstName
println("construct_02")
}
println("construct_01")
override def toString(): String = {
age + " zero " + firstName
}
}
object ClassTest {
def main(args: Array[String]): Unit = {
val a = new Person("zero", 18, "男")
println(a)
val b = new Person("zero", 18, "男", "007")
println(b)
}
}运行结果:construct_01
18 zero null
construct_01
construct_02
18 zero 007jd-gui反编译后的Person:public class Person{
private final String name;
private String firstName;
public String name(){
return this.name;
}
public int age(){
return this.age;
}
public void age_$eq(int x$1){
this.age = x$1;
}
private String firstName(){
return this.firstName;
}
private void firstName_$eq(String x$1){
this.firstName = x$1;
}
public Person(String name, int age, String gender, String firstName){
this(name, age, gender);
firstName_$eq(firstName);
Predef..MODULE$.println("construct_02");
}
public Person(String name, int age, String gender){
Predef..MODULE$.println("construct_01");
}
public String toString(){
return new StringBuilder().append(age()).append(" zero ").append(firstName()).toString();
}
}javap反编译后的结果:public class com.zero.clazz.Person {
private final java.lang.String name;
private int age;
private java.lang.String firstName;
public java.lang.String name();
public int age();
public void age_$eq(int);
private java.lang.String firstName();
private void firstName_$eq(java.lang.String);
public java.lang.String toString();
public com.zero.clazz.Person(java.lang.String, int, java.lang.String);
public com.zero.clazz.Person(java.lang.String, int, java.lang.String, java.lan
g.String);
}发现实际上scala生成了两个构造函数,主构造函数Person(String name, int age, String gender),辅助构造器也调用了主构造函数,主构造函数会将类{}里面的语句纳入到其方法类。如果喜欢传统的JavaBean风格的getter与setter,可以这样:
class Person(@BeanProperty val name: String,
@BeanProperty var age: Int,
@BeanProperty gender: String) {
}javap反编译结果:public class com.zero.clazz.Person {
private final java.lang.String name;
private int age;
public java.lang.String name();
public int age();
public void age_$eq(int);
public void setAge(int);
public java.lang.String getName();
public int getAge();
public com.zero.clazz.Person(java.lang.String, int, java.lang.String);
}可以发现将会生成四个方法,除了Scala默认的setter和getter方法,还有JavaBean风格的getter与setter方法。
本文深入探讨Scala中类的定义、构造函数的使用及如何生成getter和setter方法。通过实例展示不同构造器的调用过程及Scala如何处理类成员变量。
543

被折叠的 条评论
为什么被折叠?



