ITEEDU

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 模式,在很多应用场合都可以见到。