面向對象有三大特徵:封裝、繼承和多態。今天我們來談談多態。
多態
多態概述
什麼是多態?
每每談及多態時,總有一種只可意會不可言傳的感覺。簡單來說多態就是某個事物,在不同時刻表現出來的不同狀態。
比如:貓可以是貓的類型,也可以是動物的類型(因爲貓也是動物)。
多態的前提
- 類和類要有繼承關係。
- 要有方法重寫。沒有也行,但沒有的話多態就沒有意義了。
- 要有父類引用指向子類對象。(父類 對象名 = new 子類();)
多態中的成員的訪問特點
- 成員變量的訪問特點:編譯看左邊,運行看左邊
- 成員方法的訪問特點:編譯看左邊,運行看右邊
- 構造方法:創建子類對象時,會先訪問父類的構造方法,對父類的數據進行初始化
- 靜態方法的訪問特點:編譯看左邊,運行看左邊(靜態方法是屬於類的,算不上重寫,所以訪問還是左邊的)
多態的好處
可總結如下
- 提高了代碼的維護性(繼承)
- 提高了代碼的擴展性(多態)
多態雖然有好處,但是也有弊端。多態的弊端就是不能夠訪問子類特有的功能。(因爲是父類引用指向子類對象)
在多態的方式下,若要訪問子類特有的功能則需要向下轉型,即把父類的引用強制類型轉換爲子類的引用。
那麼有向下轉型,就有向上轉型,多態就是典型的向上轉型,父類引用指向子類對象。
抽象類
抽象類概述
在Java中,一個沒有方法體的方法應該定義爲抽象方法,而類中如果有抽象方法,該類必須定義爲抽象類。
抽象方法的格式:
修飾符 abstract 返回值類型 方法名();
抽象類的格式:
abstract class 類名{
}
那麼抽象類有哪些特點呢?
- 抽象類和抽象方法必須用abstract關鍵字修飾。
抽象類格式:abstract class 類名 {
}
抽象方法格式:public abstract void eat(); - 抽象類不一定有抽象方法,但有抽象方法的類一定是抽象類
- 抽象類中可以有構造方法,但抽象類不能進行實例化。抽象類中的構造方法是用於子類訪問父類數據時的初始化
- 抽象類雖然不能直接初始化,但可以間接初始化。按照多態的方式,由具體的子類實例化。其實這也是多態的一種,抽象類多態。
- 抽象類的子類:要麼也是抽象類;要麼重寫抽象類中的所有抽象方法
抽象類的成員特點:
- 成員變量:既可以是變量,也可以是常量。
- 構造方法:有構造方法。用於子類訪問父類數據的初始化。
- 成員方法:既可以是抽象的,也可以是非抽象的。
抽象類的成員方法特性:
- 抽象方法:強制要求子類做的事情。子類必須重寫父類的抽象方法。
- 非抽象方法:子類繼承的事情,提高代碼複用性。
一個類如果沒有抽象方法,可以定義爲抽象類,但是不能創建對象。
接口
何爲接口?
爲了體現事物功能的擴展性,Java中提供了接口來定義一些額外功能(這些額外功能並不是類的對象所共有的,只是一部分對象擁有),並不給出具體實現,當有事物向具備這些額外功能時,就可以實現這個接口
接口的特點
- 接口用關鍵字interface表示
接口的格式爲:
interface 接口名 {
}
- 類實現接口用implements表示
格式爲:
class 類名 implements 接口名 {
}
這個類,可以叫做接口的子類, 這個接口 可以叫做這個類的父接口。
- 接口不能實例化
若要實例化,則需要用多態的方式進行實例化 - 接口的子類:可以是抽象類(但是意義不大);可以是具體類,要重寫接口中的所有抽象方法(推薦這樣寫)
作爲接口的子類,有什麼要求?
- 要求子類必須重寫接口中所有的抽象方法
- 如果不想重寫,那麼這個類可以爲一個抽象類,將接口中的抽象方法繼承即可
接口成員特點
- 成員變量:只能是常量,並且是靜態的。默認修飾符:public static final,但是建議我們在寫的時候手動給出。
- 構造方法:接口沒有構造方法。
- 成員方法:只能是抽象方法。默認修飾符:public abstract,但是建議我們在寫的時候手動給出。
類、接口之間的關係:
- 類與類:繼承關係,只能單繼承,可以多層繼承。
- 類與接口:實現關係,可以單實現,也可以多實現。也可以在繼承一個類的同時實現多個接口。
- 接口與接口:繼承關係,可以單繼承,也可以多繼承。
抽象類和接口的區別:
成員的區別
- 成員變量:
抽象類中的成員變量既可以是常量,也可以是變量;
接口中的成員變量只能是靜態的常量 - 成員方法:
抽象類中的成員方法既可以是抽象的,也可以是非抽象的;
接口中的成員方法必須是抽象的 - 構造方法:
抽象類中有構造方法;
接口中沒有構造方法
關係的區別:
- 類與類:繼承關係,單繼承
- 類與接口:實現關係,單實現和多實現均可
- 接口與接口:繼承關係,單繼承和多繼承均可
設計理念的區別:
- 抽象類:被繼承 體現的是:”is a”的關係。抽象類中定義的是該繼承體系的共性功能。
- 接口:被實現 體現的是:”like a”的關係。接口中定義的是該繼承體系的擴展功能。
JDK1.8之後在接口中提供了用default修飾的方法,可以給出功能的具體實現,子類可以繼承下去用
abstract關鍵字
abstract關鍵字:抽象的,可以修飾類,也可以修飾方法。
特點:
- abstract 修飾類,此類就不能直接實例化
- abstract 修飾方法,修飾的方法,要求子類必須重寫
abstract和以下關鍵字不共存:
- private
原因:private修飾的成員不能被子類繼承,而abstract要求繼承成員,並重寫方法。 - final
衝突的原因同上。 - static
不能共存 無意義