From Gossip@Openhome

Java Gossip: 抽象類別(Abstract class)

當您定義類別時,可以僅宣告方法名稱而不實作當中的邏輯,這樣的方法稱之為「抽象方法」(Abstract method),如果一個類別中包括了抽象方法,則該類別稱之為「抽象類別」(Abstract class),抽象類別是個未定義完全的類別,所以它不能被用來生成物件,它只能被擴充,並於擴充後完成未完成的抽象方法定義。

在Java中要宣告抽象方法與抽象類別,您使用"abstract"關鍵字,直接來看個應用的例子,下面定義一個簡單的比大小遊戲抽象類別:

  • AbstractGuessGame.java
public abstract class AbstractGuessGame {
private int number;

public void setNumber(int number) {
this.number = number;
}

public void start() {
showMessage("Welcome");

int guess;
do {
guess = getUserInput();
if(guess > number) {
showMessage("bigger than the goal number");
}
else if(guess < number) {
showMessage("smaller than the goal number");
}
else
showMessage("you win");
} while(guess != number);
}

protected abstract void showMessage(String message);
protected abstract int getUserInput();
}

在宣告類別時使用"abstract"關鍵字,表示這是一個抽象類別,在這個類別中,您定義了start()方法,當中先實作比大小遊戲的基本規則,然而 您不實作與使用者互動及訊息是如何顯示的,這您分別定義為抽象方法showMessage()與 getUserInput(),在方法上使用"abstract"關鍵字,可以僅定義方法而不實作其內容。

使用這個類別的辦法是擴充它,並完成當中未定義完全的抽象方法showMessage()與getUserInput(),例如實作一個簡單的文字介面遊戲類別:

  • ConcreteGuessGame.java
import java.util.Scanner;

public class ConcreteGuessGame extends AbstractGuessGame {
private Scanner scanner;

public ConcreteGuessGame() {
scanner = new Scanner(System.in);
}

protected void showMessage(String message) {
System.out.println(message + "!");
}

protected int getUserInput() {
System.out.print("input a number: ");
return scanner.nextInt();
}
}

接下來寫個簡單的測試程式,看看這個文字介面比大小遊戲類別是不是可以運作:
  • Test.java
public class Test {
public static void main(String[] args) {
AbstractGuessGame guessGame =
new ConcreteGuessGame();
guessGame.setNumber(50);
guessGame.start();
}
}

這邊必須知道,一個基底類別的物件參考名稱,可以用來指向其衍生類別的物件而不會發生錯誤,所以上面的這個指定是可以接受的:
AbstractGuessGame guessGame =
                    new ConcreteGuessGame();
 

由於guessGame仍是AbstractGuessGame類型的參考名稱,它可以操作子類別 ConcreteGuessGame的實例中名稱相同的公開操作介面(方法),簡單的說,透過guessGame參考名稱,您可以操作 ConcreteGuessGame的實例之setNumber()與start()方法,這是多型(Polymorphism)操作的一個實際例子。

執行結果:

Welcome!
input a number: 10
smaller than the goal number!
input a number: 60
bigger than the goal number!
input a number: 50
you win!


今天如果您想要實作一個有視窗介面的比大小遊戲,則您可以擴充AbstractGuessGame並實作您的抽象方法showMessage()與 getUserInput(),事實上,上面的例子是 Template Method 模式 的一個實際例子,使用抽象類別與方法來實作Template Method 模式,在很多應用場合都可以見到。