类、超类与子类
定义子类
之前,我们写过一个Employee类,现在我们定义一个继承Employee类的子类Manager类。用关键字extends表示继承。
public class Manager extends Employee{
加入方法和域
}
关键字extends表示正在构造的新类派生于一个已存在的类。已存在的类称为超类、基类或者父类;新类称为子类或者孩子类。
尽管Employee是一个父类,但并不是因为它优于子类或者拥有比子类更多的方法,事实上,子类比父类的功能更加丰富。当子类继承父类之后,就拥有了父类的全部方法、变(常)量和域,子类可以给自己添加自己想要的方法。
在Manager类中,我们增加一个用于存储奖金信息的域,以及一个用于设置这个域的新方法:
public class Manager extends Employee{
private double bonus;
...
public void setBonus(){
this.bonus=bonus;
}
}
这个方法和域,对于属于Employee类的对象是无法调用的。只有Manager类及其子类的对象可以调用。
我们在通过扩展父类定义子类的时候,仅需要指出子类与父类的不同之处。因此在设计类的时候,应该将通用的方法放在父类,将具有特殊用途的方法放到子类中,这种将通用的功能放到父类的做法,在面向对象程序设计中用的特别多。
覆盖方法、
有的时候,父类的有些方法对子类Manager并不一定适用。具体来说,Manager类中的getSalary方法应该返回奖金和薪水的总和。为此,我们需要一个新的方法来覆盖父类中的这个方法:
public double getSalary(){
double baseSalary=super.getSalary;
return baseSalary+bonus;
}
所以,我们在子类中可以增加域,增加方法或覆盖父类的方法,但是不能删除继承来的任何域和方法。
子类构造器
在Manager类,我们提供一个构造器。
public Manager(String name,double salary,int year,int month,int day){
super(name,salary,year,month,day);
bonus=0;
}
这里的关键字super具有不同含义。super(name,salary,year,month,day)是调用父类构造器的简写。
由于Manager类的构造器不能访问Employee类的私有域,所以必须利用Employee类的构造器对这部分私有域进行初始化,我们可以通过super实现对父类构造器的调用。使用super调用构造器的语句必须是子类构造器的第一条语句。
如果子类构造器没有显示的调用父类的构造器,那么会自动调用父类默认的构造器。如果父类没有不带参数的构造器,并且在子类的构造器中没有显示地调用父类的其他构造器,将会报错。
我们回忆一下,关键字this也有两种用途:一是引用隐式参数,二是调用该类其他的构造器。同样,super关键字也有两个用途:一是调用父类的方法,二是调用父类的构造器。在调用构造器的时候,这两个关键字的使用方式很相似。调用构造器的语句只能作为另一个构造器的第一条语句出现。构造参数即可以传递给本类(this)的其他构造器,也可以传递给父类(super)的构造器。
我们看一下下面的例子:
public class test {
public static void main(String[] args) {
Manager aaa = new Manager("aaa", 800, 1998, 9, 9);
aaa.setBonus(3000);
Employee[] e = new Employee[3];
e[0]=aaa;
e[1]=new Employee("bbb",4123,1998,9,6);
e[2] = new Employee("ccc", 4564, 1997, 6, 16);
for (Employee employee : e) {
System.out.println("name= "+employee.getName()+" "+"salary "+employee.getSalary());
}
}
}
public class Manager extends Employee {
private double bonus;
public Manager(String name, double salary, int year, int month, int day) {
super(name, salary, year, month, day);
bonus=0;
}
@Override
public double getSalary() {
double basesalary= super.getSalary();
return basesalary+bonus;
}
public void setBonus(double bonus) {
this.bonus = bonus;
}
}
public class Employee {
private String name;
private double salary;
private LocalDate hireday;
public Employee(String name, double salary, int year,int month,int day) {
this.name = name;
this.salary = salary;
this.hireday = LocalDate.of(year,month,day);
}
public String getName() {
return name;
}
public double getSalary() {
return salary;
}
public LocalDate getHireday() {
return hireday;
}
public void raiseSalary(double bypercent){
double raise=salary+bypercent/100;
salary+=raise;
}
}