1. 程式人生 > 其它 >Java 抽象類(學習 Java 程式語言 045)

Java 抽象類(學習 Java 程式語言 045)

技術標籤:學習 Java 程式語言java抽象類abstract學習 Java 程式語言

如果將一個類宣告為 abstract,那麼這個類就是抽象類。抽象類可以包含抽象方法、欄位和具體方法。抽象類不能被例項化,但抽象類的物件變數可以引用了一個非抽象子類的例項。

如果自下而上在類的繼承層次結構中上移,位於上層的類更具有通用性,可能更加抽象。從某種角度看,祖先類更有一般性,人們只將它作為派生其他類的基類,而不是用來構造你想使用的特定的例項。例如,考慮擴充套件 Employee 類層次結構。員工是一個人,學生也是一個人。下面擴充套件我們的類層次結構來加入類 Person 和類 Student。下圖顯示了這三個類之間的繼承關係。

Person 及其子類的繼承圖

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;
    }
}

提示: 許多程式設計師認為,在抽象類中不能包含具體方法。建議儘量將通用的欄位和方法(不管是否是抽象的)放在超類(不管是否是抽象類)中。

抽象方法充當著佔位方法的角色,它們在子類中具體實現。

擴充套件抽象類可以有兩種選擇:

  1. 在子類中保留抽象類中的部分或所有抽象方法仍未定義,這樣就必須將子類也標記為抽象類。
  2. 定義全部的抽象方法,這樣一來,子類就不是抽象的了。

即使不含抽象方法,也可以將類宣告為抽象類。

抽象類不能被例項化。也就是說,如果將一個類宣告為 abstract,就不能建立這個類的物件。

可以定義一個抽象類的物件變數,但是這樣一個變數只能引用非抽象子類的物件。例如:
Person p = new Student("Vince Vu", "Economics");
這裡的 p 是一個抽象型別 Person 的變數,它引用了一個非抽象子類 Student 的例項。