thinking in java (三) ----- 介面與抽象類
介面的抽象類給我們提供了介面和實現分離更加結構化的方法
介面和抽象類是java中對抽象概念進行定義的兩種機制,正是因為他們的存在,才賦予了java強大的面向物件的能力。他們之間對於抽象有很大的相似,但是也有一些不同
抽象類
前面我們說過萬物皆物件,物件是通過類來描述的,但並不是所有的類都是用來描述物件的。如果一個類沒有足夠的資訊來描述一個具體的物件,而需要其他具體的類來支撐它,那麼這樣的類我們稱為抽象類。
比如new Car(),但是具體的car長什麼樣,我們是不知道的,是抽象類。我們需要一個具體的車,比如卡宴,寶馬等進行特定描述。
抽象類體現了抽象的思想,是實現多型的一種機制,他定義了一組抽象方法,其中的具體形式通過子類來實現。抽象類會被繼承,否則其沒有存在的意義。使用抽象類時,需要注意以下幾點:
- 抽象類不能被實體化,只需要提供一個引用就行了
- 抽象方法由子類進行重寫
- 只要有一個抽象方法,這個類就是抽象類
- 子類中的抽象方法不能和父類中的抽象方法一樣
- 抽象方法也可以有具體方法,可以有成員變數
- abstract修飾的方法就是需要被重寫,因此不能跟static,private並列修飾一個方法
例項
定義一個動物類Aninal,提供抽象方法cry(),貓狗為子類,如下:
public abstract class Animal { public abstract void cry(); } public class Cat extends Animal{ @Override public void cry() { System.out.println("貓叫:喵喵..."); } } public class Dog extends Animal{ @Override public void cry() { System.out.println("狗叫:汪汪..."); } } public class Test { public static void main(String[] args) { Animal a1 = new Cat(); Animal a2 = new Dog(); a1.cry(); a2.cry(); } } -------------------------------------------------------------------- Output: 貓叫:喵喵... 狗叫:汪汪...
介面
關鍵字interface將abstract的概念做了更進一步的發揮,可以想象它是純粹的abstract class,他構建出class(函式名,引數列表 返回型別)的形式,但是沒有方法體。interface中可以含有資料成員,但是自然而然成為static final。interface值提供形式,不實現細節。
介面是抽象類的延伸,介面優於抽象類的一點是能夠多實現,彌補了抽象類不能多繼承的缺陷。在使用介面的過程中,需要注意一下問題:
- interface中的所有方法都會被自動宣告為public,且只能為public
- 介面中可以宣告變數,但是是靜態變數
- 介面中不存在實現的方法
- 實現介面的非抽象類必須實現介面中所有的方法
- 介面不能被例項化
- 在實現多介面的時候注意避免方法名的重複
抽象類的介面的區別
1,語法層次
在語法層次,兩者定義不同。下面使用程式碼來說明不同之處。
抽象類:
public abstract class Demo {
abstract void method1();
void method2(){
//實現
}
}
介面:
interface Demo {
void method1();
void method2();
}
抽象類方式中,抽象類可以擁有任意範圍的成員資料,同時也可以擁有自己的非抽象方法,但是介面方式中,它僅能夠有靜態、不能修改的成員資料(但是我們一般是不會在介面中使用成員資料),同時它所有的方法都必須是抽象的。在某種程度上來說,介面是抽象類的特殊化。
對子類而言,它只能繼承一個抽象類(這是java為了資料安全而考慮的),但是卻可以實現多個介面。
2,設計層次
從設計層次上來講,才能看出兩者本質的差別
1,抽象層次不同。抽象類時對類抽象,介面是對行為的抽象。抽象類時是對類整體抽象,包括行為屬性,但是interface只是對行為進行抽象
2,跨域不同,抽象類體現的 是一種繼承關係,父類的子類必須是is-a關系,父類和子類本質上是相同的。interface則不是,interface只是是實現者對行為的實現,比如說飛機和鳥實現飛的行為
3,設計層次不同。抽象類時自下而上設計的,我們要先知道子類才能抽象出父類,而介面不需要知道子類的存在,只需要定義規則就行。
區別的例子
定義一個phone的類,裡面有打電話的方法,所有的手機都會有打電話的功能。
抽象類
abstract class Phone{
abstract void call();
}
介面
interface Phone{
void call();
}
現在增加一個功能“上網”surf,
抽象類變成了:
abstract class Phone{
abstract void call();
abstract void surf();
}
介面變為:
interface Phone{
void call();
void surf();
}
但是這樣就有些問題出現了,phone中除了固定有的方法外還混進去了一個 surf功能,這樣依賴於phone模組的就必學會上網,但是每個手機不一定都能上網(老年機)。這樣就違反了設計原則,介面汙染。
解決方法
一個使用介面,一個使用抽象類
abstract class Door{
abstract void open();
abstract void close();
}
interface Alarm{
void alarm();
}
class AlarmDoor extends Door implements Alarm{
void open(){}
void close(){}
void alarm(){}
}
這種實現方式基本上能夠明確的反映出我們對於問題領域的理解,正確的揭示我們的設計意圖。其實抽象類表示的是"is-a"關係,介面表示的是"like-a"關係。
總結
- 抽象類表示的是一種繼承關係,只能單繼承。介面表示的是一種行為規範,可以實現多個介面
- 抽象類可以擁有自己的成員變數和非抽象方法,介面中只能有靜態常量,所有的方法都沒有實現的
- 抽象類和介面的設計理念是不一樣的,抽象類體現的是is-a關係,而介面代表的是like-a關係
抽象類和介面是java中兩種不同的抽象概念,他們的存在對多型提供了好的支援,雖然他們之間語法上有很多相似性,但是他們的設計上往往體現了對問題的理解。只有對問題更好理解,才能更好設計介面和抽象類。
參考資料:作者: chenssy
出處: http://www.cnblogs.com/chenssy/