抽象
介紹關鍵字 abstract 的用法及其物件導向意義。
何謂抽象? What is Abstract?
抽象可以想像成一種概念,並不存在於世界上。
在『多型』的章節中,我們有一個Animal的類別,但現實生活中有這個東西嗎? 動物只是一個概念,並沒有一種生物叫作動物。 狗、鳥、魚都是實際存在於世界上的實體,他們都是動物,現實中卻沒有一個實體叫作動物。
如果聽起來卡卡的,再反覆讀幾次。 所以我們可以把動物視為一種『概念』,他是抽象的,不存在於世界上的。 而Dog、Bird、Fish都具備這個概念的特質,所以繼承Animal。
關鍵字 abstract
abstract 是一個Java的關鍵字,是一個修飾子,可以用來修飾的有: 1. 類別 2. 方法
抽象類別 abstract class
利用abstract來修飾類別,可以使類別變成抽象類別,使用方法:
abstract class 類別名稱{
// 成員定義...
}
在類別定義前加上修飾子abstract,就可以定義抽象類別。
上面我們提到,抽象是一個概念,而不是一個存在的實體。同樣的,抽象類別不能被實體化。
範例程式,抽象類別定義:
abstract class Animal{
int height,weight;
void move(){
System.out.println("move...move...");
}
}
範例程式,實體化測試:
class Test {
public static void main(String[] args) {
Animal ani = new Animal();
}// end of main(String[])
}// end of class Test
執行結果:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Cannot instantiate the type Animal
發生編譯錯誤,因為抽象類別無法被實體化。
阿我設計類別就是為了實體化產生物件阿,現在跟我說這個類別無法被實體化那我幹嘛要寫? 先別急,這個抽象類別無法被實體化,但是他可以『被繼承』。
class Dog extends Animal{
}
這樣Dog類別就有Animal類別定義好的東西,在加上他自己的成員,就可以用來創造Dog的物件。
因此可以說,抽象類別是用來被繼承的。
擁有這個概念的類別,繼承抽象類別,在程式撰寫上就可以利用多型的概念上程式更有邏輯性。
以上一篇『多型』的程式例子來說,Animal這個抽象的概念不應該被實體化,因為現實中不從在一種東西叫作『動物』,而狗、鳥、魚都是實際存在的東西,都擁有『動物』這個概念的特性,所以比較好的寫法應該定義為:
abstract class Animal {
// 成員定義
}
class Dog extends Animal {
// 成員定義
}
class Bird extends Animal {
// 成員定義
}
class Fish extends Animal {
// 成員定義
}
這樣寫很清楚告訴說,動物是一種概念,不能被實體化。而Dog、Bird、Fish具有動物的特性,可以被實體化存在於世界上(記憶體中)。
抽象方法 abstract method
利用修飾子abstract,可以使方法變成抽象方法,抽象方法只能寫方法的原型,無法定義方法的本體。
方法的原型? 只定義修飾子、回傳值型態、方法名稱、參數型態,而沒有『大括號{}』的部分就是方法原型。
方法的本體就是用『大括號{}』定義的東西,有寫{}就算有定義,不管裡面有沒有程式敘述。
使用格式:
abstract <修飾子> 回傳型態 方法名稱(<參數...>);
範例:
abstract void eat();
錯誤範例:
abstract void eat(){ // 編譯錯誤:Abstract methods do not specify a body
// 不管有沒有寫東西,都編譯錯誤,抽象方法不能定義方法本體
}
好,那現在問題又來了,我要這個沒有本體的抽象方法幹嘛? 只有原型的方法做不了任何事阿!
沒錯,所以必須要有其他人『覆寫』這個抽象方法。
程式範例,定義Animal為抽象類別,有一個抽象方法eat():
abstract class Animal {
abstract void eat();
}
class Dog extends Animal{
void eat(){
System.out.println("啃骨頭...");
}
}
在上述程式中,母類別Animal定義了一個抽象方法eat(),宣告這個eat()方法回傳值是void且不帶任何參數。 子類別必須覆寫這個方法,為這個方法定義本體,也就是『實作implement』這個方法。
特別注意的是,抽象方法只能定義在抽象類別中。 (否則會編譯錯誤)
abstract method can only be defined by an abstract class
有了抽象方法,那我們的抽象類別就可以定義的更簡潔了。
範例程式:
abstract class Animal{
int weight,heigh;
void setValue(int w,int h){
this.weight = w;
this.height = h;
}
abstract void eat();
}
class Dog extends Animal{
void eat(){
System.out.println("啃骨頭...");
}
}
class Bird extends Animal{
void eat(){
System.out.println("早起吃蟲...");
}
}
上述程式中,將Animal類別定義為抽象,裡面把eat()定義為抽象方法,任何繼承這個Animal的子類別都必須實作屬於他們自己的eat(),同時都擁有Animal所定義的成員。
這樣做的目的是因為繼承一個類別,子類別就可以當作母類別來使用,但一般母類別都定義的很一般化,所以透過abstract關鍵字『強制』子類別繼承這個母類別後必須實作屬於自己的方法,也讓物件導向的設計邏輯更符合一般的現實概念。
最後整理一下
關鍵字abstract,抽象,可以修飾:
類別
讓類別變成抽象類別,不能建立實體,專門用來『被繼承』。
方法
讓方法變成抽象方法,只能定義原型,專門用來『被覆寫』。
其中抽象方法只能被定義在抽象類別中。
Last updated
Was this helpful?