1. 程式人生 > >Java開發筆記(五十七)因抽象方法而產生的抽象類

Java開發筆記(五十七)因抽象方法而產生的抽象類

用法 得到 之前 public http ref 操作 使用 brush

前面介紹了類的常見用法,令人感嘆面向對象的強大,幾乎日常生活中的所有事物,都可以抽象成Java的基類及其子類。然而抽象操作也有副作用,就是某個抽象而來的行為可能是不確定的,比如半夜雞叫,如果是公雞則必定“喔喔喔”地叫,如果是母雞則必定“咯咯咯”地叫,可要是不能確定這只雞是公雞還是母雞抑或小雞,系統怎麽知道它會怎麽叫?落實到雞類Chicken的定義代碼中,它的call方法便無法給出具體的叫聲了,盡管雞類能夠派生出公雞類和母雞類,再在公雞類和母雞類重寫call方法,但是外部仍然可以創建雞類的實例,接著調用雞類實例的call方法,此時該期望這只雞發出什麽叫聲呢?不管是讓雞類胡言亂語、語無倫次,還是讓雞類默不作聲、噤若寒蟬,顯然都與真實情況有很大出入。
由此可見,某些類其實並不能拿來直接使用,充其量只能算半成品,必須經過進一步的加工,形成最終的成品方能給外部調用。鑒於前述的雞類存在叫喚這個不確定的方法,故而理應將它歸入半成品之列;至於由雞類派生而來的公雞類與母雞類,因為包括叫喚在內的每個方法都是明確的,所以它們才成為機能鑒權的完整類。在Java編程中,功能不確定的方法被稱作抽象方法,而包含抽象方法的類受到牽連就變成了抽象類。在類的定義代碼裏面,通過關鍵字abstract來標識抽象方法及抽象類;凡是被abstract修飾的抽象方法,由於方法的具體實現並不明確,因此抽象方法沒有花括號所包裹著的方法體;凡是被abstract修飾的抽象類,由於包含了至少一個抽象方法,因此不允許外部創建抽象類的實例,否則就會出現雞類實例不知如何叫喚的尷尬。除此之外,抽象類還有下列兩點需要註意:
1、abstract只能用來修飾抽象方法和抽象類,不可用於修飾成員屬性,因為屬性值本身就允許通過賦值來改變,無所謂抽象不抽象。
2、雖然抽象類依舊可以擁有構造方法,但它的構造方法並不能被外部直接調用,因為外部不允許通過構造方法來創建抽象類的實例,抽象類的構造方法只能提供給它的子類調用。
絮絮叨叨了這麽多抽象概念,接著嘗試把之前的雞類改寫成抽象類,修改後的抽象雞類定義代碼示例如下:

//演示抽象類的定義
abstract public class Chicken {

	// 定義一個名稱屬性
	public String name;
	// 定義一個性別屬性
	public int sex;
	
	// 定義一個抽象的叫喚方法。註意後面沒有花括號,並且以分號結尾
	abstract public void call();

	// 即使抽象類定義了構造方法,外部也無法創建它的實例
	public Chicken() {
	}

	// Java只有抽象類和抽象方法,沒有抽象屬性的說法
	//abstract public String cry;
}

然後分別編寫繼承自雞類的公雞類和母雞類,其中雞類的抽象方法call是必須在子類中重寫的,只有這樣,派生而來的子類才具備所有完善的行為動作;否則的話,這個子類仍舊是個尚未完工的半成品,依然屬於抽象類的行列。下面是重寫了call方法的公雞類代碼例子:

//定義一個繼承自抽象雞類的公雞類
public class Cock extends Chicken {
	
	public Cock() {
		// 公雞的性別固定為雄性
		sex = 0;
	}

	// 重寫了公雞的叫喚方法。如果不重寫父類的抽象方法,那麽該子類仍舊為抽象類
	public void call() {
		System.out.println("喔喔喔");
	}
}

同樣重寫了call方法的母雞類代碼如下所示:

//定義一個繼承自抽象雞類的母雞類
public class Hen extends Chicken {
	
	public Hen() {
		// 母雞的性別固定為雌性
		sex = 1;
	}

	// 重寫了母雞的叫喚方法。如果不重寫父類的抽象方法,那麽該子類仍舊為抽象類
	public void call() {
		System.out.println("咯咯咯");
	}
}

最後輪到外部調用各種雞類了,對於外部而言,唯一的區別是外部不能創建抽象類的實例,其它子類的調用則跟從前一樣沒有變化。具體的外部調用代碼見下:

		// 不能創建抽象類的實例,因為抽象類是個尚未完工的類
		//Chicken chicken  = new Chicken();
		// 創建一個公雞實例,公雞類繼承自抽象類Chicken
		Cock cock = new Cock();
		cock.call(); // 調用公雞實例的叫喚方法
		// 創建一個母雞實例,母雞類繼承自抽象類Chicken
		Hen hen = new Hen();
		hen.call(); // 調用母雞實例的叫喚方法

運行上面的調用代碼,得到以下的日誌結果,可見子類重寫後的call方法正常工作。

喔喔喔
咯咯咯

  

更多Java技術文章參見《Java開發筆記(序)章節目錄》

Java開發筆記(五十七)因抽象方法而產生的抽象類