若是将一个类声明为 abstract,那么这个类就是抽象类。抽象类能够包含抽象方法、字段和具体方法。抽象类不能被实例化,但抽象类的对象变量能够引用了一个非抽象子类的实例。java
若是自下而上在类的继承层次结构中上移,位于上层的类更具备通用性,可能更加抽象。从某种角度看,祖先类更有通常性,人们只将它做为派生其余类的基类,而不是用来构造你想使用的特定的实例。例如,考虑扩展 Employee 类层次结构。员工是一我的,学生也是一我的。下面扩展咱们的类层次结构来加入类 Person 和类 Student。下图显示了这三个类之间的继承关系。程序员
Person.javaide
public abstract class Person { public abstract String getDescription(); private String name; public Person(String name) { this.name = name; } public String getName() { return this.name; } }
Employee.javathis
public class Employee extends Person { private double salary; private LocalDate hireDay; 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 raiseSalary(double byPercent) { double raise = salary * byPercent / 100; salary += raise; } }
Student.java3d
public class Student extends Person { private String major; public Student(String name, String major) { super(name); this.major = major; } public String getDescription() { return String.format("a student majoring in " + major); } }
为何要那么麻烦提供这样一个高层次的抽象呢?每一个人都有一些属性,如姓名。学生与员工都有姓名属性,所以经过引入一个公共的超类,咱们就能够把 getName 方法放在继承层次结构中更高的一层。code
如今,在增长一个 getDescription 方法,它能够返回对一我的的简短描述。例如:
an employee with a salary of $5,000.00
a student majoring in computer science
在 Employee 类和 Student 类中实现这个方法很容易。可是在 Person 类中应该提供什么内容呢?除了姓名以外,Person 类对这我的一无所知。固然,可让 Person.getDescription() 返回一个空字符串。不过还有一个更好地方法,就是使用 abstract 关键字,这样就彻底不须要实现这个方法了。
public abstract String getDescription();
orm
为了提升程序的清晰度,包含一个或多个抽象方法的类自己必须被声明为抽象的。对象
public abstract class Person { ... public abstract String getDescription(); }
除了抽象方法以外,抽象类还能够包含字段和具体方法。例如,Person 类还保存着一我的的姓名,另外有一个返回姓名的具体方法。blog
public abstract class Person { public abstract String getDescription(); private String name; public Person(String name) { this.name = name; } public String getName() { return this.name; } }
提示: 许多程序员认为,在抽象类中不能包含具体方法。建议尽可能将通用的字段和方法(无论是不是抽象的)放在超类(无论是不是抽象类)中。继承
抽象方法充当着占位方法的角色,它们在子类中具体实现。
扩展抽象类能够有两种选择:
即便不含抽象方法,也能够将类声明为抽象类。
抽象类不能被实例化。也就是说,若是将一个类声明为 abstract,就不能建立这个类的对象。
能够定义一个抽象类的对象变量,可是这样一个变量只能引用非抽象子类的对象。例如:
Person p = new Student("Vince Vu", "Economics");
这里的 p 是一个抽象类型 Person 的变量,它引用了一个非抽象子类 Student 的实例。