Java 抽象類(學習 Java 程式語言 045)
技術標籤:學習 Java 程式語言java抽象類abstract學習 Java 程式語言
如果將一個類宣告為 abstract,那麼這個類就是抽象類。抽象類可以包含抽象方法、欄位和具體方法。抽象類不能被例項化,但抽象類的物件變數可以引用了一個非抽象子類的例項。
如果自下而上在類的繼承層次結構中上移,位於上層的類更具有通用性,可能更加抽象。從某種角度看,祖先類更有一般性,人們只將它作為派生其他類的基類,而不是用來構造你想使用的特定的例項。例如,考慮擴充套件 Employee 類層次結構。員工是一個人,學生也是一個人。下面擴充套件我們的類層次結構來加入類 Person 和類 Student。下圖顯示了這三個類之間的繼承關係。
Person.java
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.java
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.java
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 方法放在繼承層次結構中更高的一層。
現在,在增加一個 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();
為了提高程式的清晰度,包含一個或多個抽象方法的類本身必須被宣告為抽象的。
public abstract class Person
{
...
public abstract String getDescription();
}
除了抽象方法之外,抽象類還可以包含欄位和具體方法。例如,Person 類還儲存著一個人的姓名,另外有一個返回姓名的具體方法。
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 的例項。