ContactPerson no1 = new ContactPerson("Tom");
System.out.println("只知姓名的联系人:" + no1.getName());
ContactPerson no2 = new ContactPerson("Jerry",
"13812345678");
System.out.println("知道姓名、电话的联系人:"
+ no2.getName() + " " + no2.getSelfphone());
ContactPerson no3 = new ContactPerson("Jane",
"13887654321", "[email protected]");
System.out.println("知道姓名、电话和email的联系人:" +
no3.getName() + " " + no3.getSelfphone() + " " + no3.getEmail());
} }
运行结果如图 5-15 所示。
图 5-15 例 5-17 运行结果
ContactPerson 类根据联系人信息的完整程度,定义了 3 个版本的构造方法以适应需求。
第 3 个版本的构造方法中,利用 this 调用了第 2 个版本的构造方法:
public ContactPerson(String name, String selfphone)
该构造方法实现了给 name 和 selfphone 初始化并直接调用,在第 3 个版本的构造方法中 就不必重复书写初始化语句了。事实上,注释[1]处也可以换成 this 调用构造方法 this(name)。
在 OverloadTest2 中,根据联系人信息的完整程度不同,分别调用了不同版本的构造方法 创建了联系人对象,具体调用哪个版本的构造方法由调用时给定的实际参数列表与形参列表匹 配而定。
需要注意的是:
重载构造方法时,若要使用 this 调用其他版本的构造方法,则该 this 调用语句必须作 为构造方法的方法体中的第一条语句。
5.7 继承
继承是实现代码重用的一种有力手段。如果有多个类具有一些相同的属性和方法,可以 将这些相同的属性和方法抽象出来定义为一个父类,在父类中定义这些属性和方法,则具有这
些属性和方法的其他类可以从这个父类派生出来,不必再重新定义这些属性和方法,我们称这 些派生而来的类为子类。
5.7.1 类的继承
类的继承,利用已有的类来创建新类,在父类中定义过的属性和方法,子类中可以不用 重新定义,可实现代码重用,降低编码和维护的工作量。
在继承关系中,被继承的类称为父类 、超类或基类,其中定义了子类所共有的属性和方 法。由继承方式创建的类称为子类,子类将父类的属性和方法继承过来,不必重新定义,并且 可根据需要增加新的属性和方法。
Java 的所有类都直接或间接地继承自 java.lang.Object 类。类定义没有用 extends 继承某个 类时,实际上隐式继承了 Object 类。
类的继承示例如图 5-16 所示。
图 5-16 类的继承
Java 中类的继承用关键字 extends 实现,用继承来定义一个新类的格式如下所示:
class SonClass extends SuperClass {
……
}
上述代码表示 SonClass 类继承了 SuperClass 类,将继承 SuperClass 类中所有的非 private 的成员变量和成员方法。private 是访问控制符,被 private 修饰的变量和方法都只能在本类中 访问(参见 5.9 节)。
与 C++不同的是,Java 是单继承的,一个子类只能有一个直接的父类,如果出现类似如 下的类定义,编译时将会报错:
class SonClass extends SuperClass1,SuperClass2,SuperClass3,…{
……
}
下面是一个继承的示例,定义一个描述人的共有信息的父类,社会关系中各种各样不同 的人就可以从这个类继承而来,再添加上能表现自己独特性的属性和方法即可。
为与前面的例子中的类区分开来,这里将描述人共有信息的父类命名为 Person2,由 Person2 派生而来的学生子类命名为 Student2。
例 5-18 Person2.java,Student2.java2 public class Person2 {
String name;
String sex;
int age;
public Person2(String name, String sex, int age) { this.name = name;
this.sex = sex;
this.age = age;
}
public String getName() { return name;
}
public void setName(String name) { this.name = name;
}
public String getSex() { return sex;
}
public void setSex(String sex) { this.sex = sex;
}
public int getAge() { return age;
}
public void setAge(int age) { this.age = age;
}
public void display() {
System.out.println("This person's information : \n");
System.out.println("Name : " + name);
System.out.println("Sex : " + sex);
System.out.println("Age : " + age);
} }
public class Student2 extends Person2{
String majorClass; //新增属性:专业班级
public Student2(String name, String sex, int age, String majorClass){
super(name,sex,age); //调用父类的构造方法
this.majorClass = majorClass;
}
//新增方法
public String getMajorClass(){
return majorClass;
}
public void setMajorClass(String newMajorClass){
majorClass = newMajorClass;
}
//重写父类的 display 方法 public void display(){
System.out.println("This Student's information : \n");
System.out.println("Name : " + name);
System.out.println("Sex : " + sex);
System.out.println("Age : " + age);
System.out.println("Major Class : " + majorClass);
} }
在子类 Student2 中,虽然只有 1 个成员变量的定义,但事实上包含 4 个成员变量,其中 3 个从父类 Person2 继承而来。构造方法实现给所有 4 个成员变量进行初始化操作,其中
super(name,sex,age)的作用是调用父类
Person2 的构造方法,实现对从父类继承来的 3 个 变量进行初始化操作。成员方法也是如此,除了子类特有的新增成员变量 majorClass 的 get 和 set 方法外,还有 其他 3 个变量的 get 和 set 方法从父类继承而来。
父类中包含显示一个大众化的 person 信息的 display()方法,而对于学生而言,需要显示的 信息还要包括代表学生特征的部分,即 majorClass,则父类的 display()方法对于子类不适用,
但方法的功能是一样的,这时候子类可以定义一个跟父类同名的方法,返回类型、参数列表都 相同,这样子类方法就覆盖(或叫重写)了父类的方法,子类对象调用 display()方法时调用的 就是子类的版本了。
如下例所示,创建子类 Student2 的对象,并显示学生的相关信息。
例 5-19 Student2Test.java