Head First Java學習:第八章-接口和抽象類
第八章:接口和抽象類
深入多態
1、抽象類:有些類不應該被初始化
在類聲明前面加上抽象類的關鍵字,abstract。
- 防止類被初始化,即不能被“new”創建該類的實例(要求)
- 還是可以用這種抽象的類型作為引用類型,給多態使用(目的)
abstract class Canine extends Animal{
public void roam(){}
}
2、編譯器不會讓你初始化抽象類
編譯的時候就會報錯。抽象類除了被繼承之外,是沒有用途,沒有值,沒有目的。
3、抽象的方法
- 抽象的方法沒有實體:
public abstract void eat();
- 如果申明一個抽象的方法,必須將類也標記為抽象。不能在非抽象類中擁有抽象方法
為什么要有抽象的方法?
將可以繼承的方法體放到父類中。但有時就是沒有辦法作出給任何子類有意義的共同程序代碼。抽象方法的意義就算無法實現出方法的內容,但還是可以定義出一組子型共同的協議。
抽象的方法有什么好處?
答:可以使用多態!你想達成的目標是要使用父型作為方法的參數、返回類型或數組的類型。通過這個機制,你可以加入新的子型到程序中,卻不必重寫或修改處理這些類型的程序。
- 必須實現所有抽象的方法
實現抽象的方法就如同覆蓋過方法一樣。
抽象的方法沒有內容,它只是為了標記出多態而存在。這表示在繼承樹結構下的第一個具體類,必須要實現出所有的抽象方法。
可以通過抽象機制將實現的負擔轉給下層。
4、多態的使用
自行描寫維護list的類,以保存Dog對象。

如果要寫出給Cat 用的:

5、所有的類都繼承自:Object類
Object類的常用方法:
- equals(Object o) 比較兩個對象是否“相等”
- hashCode() 列出詞對象的哈希代碼,可以想像成唯一id
- getClass() 告訴你此對象是從哪里被初始化的
- toString() 列出類的名稱和對象在堆中存放的地址
數字是對象在堆中存放的地址。
6、使用Object類型的多態引用是會付出代價的
任何從 ArrayList<Object> 取出來的東西都會被當作 Object類型的引用,而不管原來放進去是什么。
編譯器是根據引用類型來判斷有哪些method 可以調用。
o.hashCode();
o 被聲明為Object的引用,所以只能通過o調用Object類中的方法。
7、探索內部Object
對象會帶有從父類繼承下來的所有東西。這代表每個對象,不論實際類型,也會是個Object的實例。所以java中的每個對象除了真正的類型外,也可以當作是Object 來處理。當你執行new Snowboard() 命令時,除了在堆上會有一個Snowboard對象外,此對象也包含了一個Object在里面。

- 把對象裝進 ArrayList<Object> 時,不管它原來是什么,只能把它當作 Object
- 從ArrayList<Object> 取引用,引用的類型只會是object。
8、如何轉換回原來的類型:強制轉換
Object o = al.get(index);
Dog d = (Dog) o;
d.roam();
檢查是否是 Dog類型,使用:instanceof
如果類型錯誤,執行期間會報 ClassCastException。
9、多重繼承的問題
導致“致命方塊”問題。

10、接口:interface
所以的接口方法都是抽象的
接口的定義:public interface Pet {…}
接口的實現:public class Dog extends Canine implements Pet {…}
設計和實現Pet接口:
public interface Pet {
// 接口的方法一定是抽象的,所以必須以分號結束
public abstract void beFriendly();
public abstract void play();
}
public class DogNew extends Animal implements Pet{
public void beFriendly(){
// 必須實現出Pet的方法
}
public void play(){
// 必須實現出Pet的方法}
}
}
使用接口你就可以繼承超過一個以上的來源。
類可以 extend 過某個父類,并且實現其他接口,同時其他的類也可以實現同一個接口。
如果使用接口來編寫程序,你就會說,不管你來自哪里,別人就會知道你一定會履行這個合約。
11、不同繼承樹的類也可以實現相同的接口

對于這棵繼承樹,定義為 Canine 類型的參數可以接受 Wolf和Dog,但是無法忍受 Cat 或 Hippo。
但當你用接口來作為多態類型時,對象就可以來自任何地方了,唯一的條件就是該對象必須是來自有實現此接口的類。
類可以實現多個接口。
12、在子類中調用父類的方法:super
可以做在父類中設計出所有子類都使用的功能實現,讓子類可以不用完全覆蓋掉父類的功能,只是再加上額外的行為,可以通過 super這個關鍵字取用父類。
abstract class Report {
// 父類的方法,子類可以運行
void runReport(){
// 設置報告
}
void printReport(){
// 輸出
}
}
public class BuzzwordsReport extends Report{
void runReport(){
// 調用父類的方法
super.runReport();
buzzwordCompliance();
printReport();
}
void buzzwordCompliance(){
//...
}
}
執行super.runReport();
對子類的對象調用會去執行子類覆蓋過的方法,但在子類中可以去調用父類的方法。

12、總結
- 不想讓某個類被初始化:abstract標記為抽象的
- 抽象類 = 抽象方法+非抽象方法+實例變量
- 抽象方法沒有內容,它的聲明是以分號結束
- 抽象的方法必須在具體的類中運用
- Java所有的類都是 Object(lang.Object)直接或間接的子類
- 方法可以申明Object的參數或返回類型。
- 不管實際上所引用的對象時什么類型,只有在引用變量的類型就是帶有某方法的類型時才能調用該方法。
- Object引用變量在沒有類型轉換的情況下不能賦值給其他的類型,若堆上的對象類型與所要轉換的類型不兼容,則此轉換回在執行期間產生異常。
- 從ArrayList<Object> 取出的對象只能被Object 引用,不然就要用類型轉換來改變。
- java不允許多重繼承,因為那樣會有致命方塊的問題。
- 接口就是 100% 純天然抽象類。
- 以interface 這個關鍵字取代class 來聲明接口。
- 實現接口時要使用 implements 這個關鍵詞
- class 可以實現多個接口
- 實現某接口的類必須實現它所有的方法,因為這些方法都是 public 與 abstract的。
- 要從子類調用父類的方法,可以用 super這個關鍵詞來引用。
浙公網安備 33010602011771號