Person与子类的关系图
每一个人都有一些诸如名字这样的属性,学生与雇员都有名字属性,因此可以将getName方法放在位于继承关系较高层的通用超类(父类)中,现在增加一个getDescription方法,返回对一个人的简短描述,例如:
an employee with a salary of $50000.00
a student majoring in Computer science
在雇员类和学生类中实现这个方法很容易,但是在Person类中应该提供什么内容呢?
除了姓名之外,person类一无所知。使用abstract关键字,就可以完全不用实现这个方法了。
扩展抽象类有两种选择:一是在抽象类中定义部分抽象类方法或不定义抽象类方法,这样就可以将子类也标记位抽象类;另一种是定义全部的抽象类方法,这样一来,子类就不是抽象的了。
例如,通过扩展抽象Person类,并实现getDescription方法来定义Student类,由于在Student类中不在含有抽象方法,就不必将这个类声明为抽象的。
有些人可能会对下面这个调用感到困惑:
p.getDescription();
这不是调用了一个没有定义的方法吗?其实,由于不能构造抽象类person的对象,所以变量p永远也不会引用person对象,而是引用诸如Employee类或Student类这样的具体子类对象,二这些对象都定义了getDescription方法。
程序清单如下:
import java.time.LocalDate;
public class PersonTest {
public static void main(String[] args) {
Person[] people=new Person[2];
people[0]=new Employee("Harry",50000,1989,10,12);
people[1]=new Student("Maria","Computer science");
for(Person p:people)
System.out.println(p.getName()+","+p.getDescription());
}
}
public abstract class Person {
public abstract String getDescription();//不需要实现此方法
private String name;
public Person(String name){
this.name=name;
}
public String getName(){
return name;
}
}
public class Employee extends Person{
private double salary;
private LocalDate hireDay;
public Employee(String name,double salary,int year,int month,int day){
super(name);
this.salary=salary;
hireDay=LocalDate.of(year,month,day);
}
public double getSalary(){
return salary;
}
public LocalDate getHireDay(){
return hireDay;
}
public String getDescription(){
return String.format("an employee with a salary of $%.2f",salary);
}
public void RiaseSalary(double percent){
double raise=salary*percent/100;
salary+=raise;
}
}
public class Student extends Person{
private String major;
public Student(String name,String major){
super(name);
this.major=major;
}
public String getDescription(){
return "a student majoring in "+major;
}
}
运行结果:
不能省略Person超类的抽象方法,而仅在Employee类和Student类中定义getDescription方法。如果这样的话,就不能通过变量p调用getDescription方法了,编译器只允许调用在类中声明的方法。