若是將一個類聲明爲 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 的實例。