“你好,阿米戈!我們有一個有趣的新話題。”
“今天真是話題多多的一天!”
“為什麼要謝你!”
“不客氣。”
“還記得我們引入 ChessItem 基類來簡化所有棋子類嗎?”
“是的。”
“現在假設每個棋子都有一個方法來處理在屏幕上渲染棋子。您調用該方法,棋子會在其當前坐標處自行繪製。將此方法移至基類中是否有幫助?”
“是的。” 在了解多態性之後,我將能夠為所有片段調用 render 方法,而不管它們是什麼類型。像這樣的東西:“
class ChessBoard
{
public void drawAllChessItems()
{
//draw them regardless of their type.
ArrayList <ChessItem> items = new ArrayList<ChessItem>();
items.add(new King());
items.add(new Queen());
items.add(new Bishop());
//draw them regardless of their type.
for (ChessItem item: items)
{
item.draw();
}
}
}
“幹得好。完全正確。ChessItem 類本身的 draw 方法會做什麼?”
“我不知道。國際象棋沒有這樣的棋子。這意味著它沒有視覺表現。”
“準確地說。創建一個 ChessItem 對像沒有意義。沒有這樣的棋子。它只是一個抽象——我們為了方便而創建的類。這就是抽像在 OOP 中的工作方式:我們移動了所有重要的(共享的)將所有棋子)數據和方法放入一個基類中,但我們將它們的差異保留在對應於特定棋子的類中。”
Java 為此有一個特殊的類類型:抽像類。關於抽像類,需要記住以下三點。
1) 抽像類可以聲明方法而不實現它們。這樣的方法稱為抽象方法。
public abstract class ChessItem
{
public int x, y; //coordinates
private int value; //the piece's "value"
public int getValue() //an ordinary method, returns value
{
return value;
}
public abstract void draw(); //abstract method. There is no implementation.
}
2) 抽象方法用關鍵字abstract標記。
如果一個類只有一個抽象方法,那麼這個類也被標記為abstract。
3) 不能創建抽像類的對象。試圖這樣做的代碼根本無法編譯。
Java代碼 | 描述 |
---|---|
|
此代碼無法編譯。 |
|
但你可以做到這一點。 |
4)如果你的類繼承了一個抽像類,你需要覆蓋所有繼承的抽象方法,即你必須實現它們。否則,您的類也必須聲明為抽像類。如果該類甚至有一個未實現的方法直接在類中聲明或從父類繼承,則該類被認為是抽象的。
“但是為什麼這一切都是必要的?為什麼我們需要抽像類?難道不能使用普通類來代替嗎?除了抽象方法,我們不能只創建由左右大括號組成的空實現嗎?”
“你可以。但這些限制就像修飾符private
。我們使用private
修飾符來故意阻止對數據的直接訪問,以便其他程序員和他們的類使用我們的public
方法。”
這同樣適用於抽像類。編寫該類的人不希望任何人創建該類的實例。相反,作者希望他或她的抽像類的抽象方法被繼承和覆蓋。
“我仍然不明白為什麼我們要以這種方式使我們的生活複雜化。”
“這個特性的優勢在大型項目中很明顯。你擁有的類越多,你就越需要清楚地劃分他們的角色。你會看到這樣做的優勢,很快。每個人都必須經歷這一點。”
GO TO FULL VERSION