在面向對象的概念中,我們知道所有的對象都是通過類來描繪的,但是並不是所有的類都能用來描繪對象的,如果一個類中沒有包含足夠的信息來描繪一個具體的對象,這樣的類就應該被定義為抽象類。
比如,我們要描述“動物”,它具有年齡、體積,會叫,能跑。但是又缺乏足夠的特性(相較於阿貓,阿狗,它們都是動物,卻有自己的特性),我們沒有唯一的一種能夠代表動物的東西(當然,這是相對於貓、狗來說的,在生物學上,動物還是有辦法來定義的),這時我們可以用抽象類來描述它。當我們用某個類來具體描述“貓”時,這個類就可以繼承“動物”這個抽象類,然後加以具體描述。抽象類的子類在類中必須實現抽象類中的抽象方法,比如說動物類中的跑和叫,在子類中(貓類,狗類)必須實現其是如何跑,怎麼叫。抽象方法沒有方法體,且用abstract修飾。
下面我們來系統的介紹一下抽象類:
a. 抽象方法和抽象類用關鍵字abstract表示。
b. 抽象類不能被實例化
c. 有抽象方法的類一定是抽象類(或者接口);抽象類中不一定有抽象方法。
d. 如果一個類繼承抽象類,那麼這個類要麼本身也是抽象類,要麼這個類重寫父類的所有抽象方法。
強制要求子類必須完成某些功能。
A. 成員變量 -- 可以有成員變量,也可以有常量
B. 構造方法 -- 有構造方法,用於子類訪問父類之前,對父類數據進行初始化。
C. 成員方法 -- 可以有抽象方法,也可以有關非抽象方法。
i. 抽象方法是為了要求子類做某些事情。
ii. 非抽象方法時為了提高代碼復用性,被子類繼承。
注意:
不能與final、private、static 共存。
public abstract class AbstractClass //裡面至少有一個抽象方法
{
public int a; //普通數據成員
public abstract void method1(); //抽象方法,抽象類的子類在類中必須實現抽象類中的抽象方法
public abstract void method2();
public void method3(); //非抽象方法
publicvoid method3(){
…… //抽象類中可以賦予非抽象方法方法的默認行為,即方法的具體實現
}
}
是一種特殊的抽象類。比抽象類更抽象,因為它裡面的方法都是抽象的。
Class 類名 implements 接口名
{
}
A. 接口不能實例化。
B. 接口中的方法:
a) 要麼被子類重寫
b) 要麼子類也是抽象類。
成員變量 -- 接口中只有常量。
因為接口的成員變量有默認修飾符。推薦:永遠自己給出修飾符,public static final
構造方法 -- 接口中沒有構造方法。
任何類如果沒有繼承父類,那麼這個類就繼承Object類
成員方法 -- 接口中的方法都是抽象的。
因為接口中的 成員方法有默認修飾符。推薦:永遠自己給出修飾符,public abstract
1. 對外暴露的規則。
2. 程序的功能擴展
3. 降低耦合性
4. 用來多實現。
interface Interface
{
public static final int i; //接口中不能有普通數據成員,只能夠有靜態的不能被修改的數據成員,static表示全局,final表示不可修改,可以不用static final 修飾,會隱式的聲明為static和final,但是建議永遠自己給出修飾符public static final
public abstract void method1(); //接口中的方法一定是抽象方法,所以可以不用abstract修飾,但是建議永遠自己給出修飾符public abstract
public void method2(); //接口中不能賦予方法的默認行為,即不能有方法的具體實現。(注意,此處及省略了abstract.)
}
class zi implements Interface
{
publicvoid method1()
{
…… //把接口中的抽象方法重寫
}
public void method2()
{
…… //注意,是把抽象方法全部重寫(接口裡的方法全部是抽象方法)
}
}
//另一種情況,子類也是抽象類,此時可以不重寫接口中的方法
/*
abstract class zi implements Interface
{
public abstract void method1(); //沒有重寫
public void method2() //重寫了method2()
{
System.out.println("重寫了method2()");
}
}
*/
抽象類
接口
成員特點
成員變量
變量或常量
常量
默認修飾符 public static final
構造方法
有
無
成員方法
抽象方法或非抽象方法
抽象方法
默認修飾符public abstract
設計理念
理念
被繼承,定義的是整個繼承體系的共性內容
被實現,定義的是整個體系的擴展內容
體現
is a
like a
關系特點
類與類
繼承關系,只能單繼承,可以多層繼承
類與接口
實現關系,可以單實現,也可以多實現。還可以繼承一個類的同時,實現多個接口。
接口與接口
繼承關系,可以單繼承,也可以多 繼承。
進一步理解,關於Java中引入抽象類、接口的目的,度娘上有高手的答復如下:
1、從類的層次結構上看,抽象類是在層次的頂端,但在實際的設計當中,一般來說抽象類應當是後面才會出現。為什麼?實際上抽象類的獲取有點像數學中的提取公因式:ax+bx,x就是抽象類,如果你沒有前面的式子,你怎麼知道x是不是公因式呢?在這點上,也符合人們認識世界的過程,先具體後抽象。因此在設計過程中如果你得到大量的具體概念並從當中找到其共性時,這個共性的集合就是抽象類應當是沒錯的。
2、interface從表面上看,和抽象類很相似,但用法完全不同。它的基本功能就是把一些毫不相關的類(概念)集合在一起形成一個新的、可集中操作的“新類”。一個典型的例子就是“司機”。誰可以當司機?誰都可以,只要領取了駕照。所以不管你是學生,白領、藍領還是老板,只要有駕照就是司機。
interface DriverLicence {
Licence getLicence();
}
class StudentDriver extends Student implements DriverLicence
{
}
class WhtieCollarEmployeeDriver extends WhtieCollarEmployee implements DriverLicence
{
}
class BlueCollarEmployeeDriver extends BlueCollarEmployee implements DriverLicence
{
}
class BossDriver extends Boss implements DriverLicence
{
}
當我定義了“汽車”類後,我就可以指定“司機”了。
class Car {
setDriver(DriverLicence driver);
}
這時候,Car的對象並不關心這個司機到底是干什麼的,他們的唯一共同點是領取了駕照(都實現了DriverLicence接口)。這個應當是接口最強大的地方也是抽象類無法比擬的。
抽象類是提取具體類的公因式,而接口是為了將一些不相關的類“雜湊”成一個共同的群體,因而實用性可能更高一點。兩者的出現一方面是減少了代碼量,提高了效率,另一方面照應前面提到的繼承和多態,使得程序符合面向對象的思想特點,對修改關閉,對拓展開放。