爲什麼要有繼承
多個類中存在相同屬性和行爲時,將這些內容抽取到單獨一個類中,那麼多個類無需再定義這些屬性和行爲,只要 繼承那一個類即可。其中,多個類可以稱爲子類,單獨那一個類稱爲父類、超類(superclass)或者基類。
繼承的概念
繼承:就是子類繼承父類的屬性和行爲,使得子類對象具有與父類相同的屬性、相同的行爲。子類可以直接訪問父類中的非私有的屬性和行爲。繼承描述的是事物之間的所屬關係,這種關係是: is-a 的關係。繼承的關係中,“子類就是一個父類”,也就是說子類可以被當做父類看待。例如,兔子屬於食草動物,食草動物屬於動 物。可見,父類更通用,子類更具體。我們通過繼承,可以使多種事物之間形成一種關係體系。繼承主要解決的問題是共性抽取。
好處
- 提高代碼的複用性。
- 類與類之間產生了關係,是多態的前提。
繼承關係當中的特點
- 子類擁有父類中非私有的屬性和行爲
- 子類還可以擁有自己獨有的屬性和行爲
繼承的格式
通過 extends 關鍵字,可以聲明一個子類繼承另外一個父類,定義格式如下:
注意:父類只是一個普通的類
代碼舉例
定義父類
package demo01;
// 定義一個父類
public class MyFather {
//父類中的成員變量
public int age = 18;
//父類中的成員方法
public void method() {
System.out.println("我是父類中的方法");
}
}
定義子類
package demo01;
// 定義一個子類
public class MySon extends MyFather {
}
定義測試類
package demo01;
public class MyTest {
public static void main(String[] args) {
//創建子類對象
MySon son = new MySon();
//子類裏面什麼代碼都沒有,但是繼承了父類中非私有的方法和屬性
son.method();
System.out.println(son.age);
}
}
代碼運行之後結果
繼承中成員變量的訪問特點
創建父類對象
- 只能使用父類的成員變量,沒有任何子類的成員變量
創建子類對象
- 子類對象可以使用本類中的成員變量或者使用父類中非私有的成員變量
- 如果子類父類中出現不重名的成員變量,這時子類對象可以根據不同的成員變量名來訪問需要的成員變量。
- 如果子類父類中出現重名的成員變量,這時子類對象有2種訪問方式
訪問方式1:直接通過子類對象訪問成員變量:等號左邊是誰,就優先用誰,沒有則向上(父類)找。
訪問方式2:間接通過成員方法訪問成員變量:該方法屬於誰,就優先用誰,沒有則向上(父類)找
訪問成員變量的三種方式
- 訪問局部變量 格式:直接寫成員變量名
- 訪問本類的成員變量: 格式: this.成員變量名
- 訪問父類的成員變量: 格式:super.成員變量名
繼承中成員方法的訪問特點
創建父類對象
- 只能使用父類的成員方法,沒有任何子類的成員方法
創建子類對象
- 子類對象可以使用本類中的成員方法或者使用父類中非私有的成員方法
- 訪問成員方法的規則:創建的對象是誰,就優先用誰,如果沒有則向上(父類)找。
方法重寫 (Override)
如果子類父類中出現重名的成員方法,這時的訪問是一種特殊情況,叫做方法重寫 (Override)。
- 方法重寫 :子類中出現與父類一模一樣的方法時(返回值類型,方法名和參數列表都相同),會出現覆蓋效 果,也稱爲重寫或者複寫。簡單理解:聲明不變,重新實現。
方法重寫的注意事項:
1. 必須保證父子類之間方法的名稱相同,參數列表也相同。
- tips:@Override:寫在方法前面,用來檢測是不是有效的正確覆蓋重寫。這個註解就算不寫,只要滿足要求,也是正確的方法覆蓋重寫。
2. 子類方法的返回值必須【小於等於】父類方法的返回值範圍。
- tips:java.lang.Object類是所有類的公共最高父類(祖宗類),java.lang.String就是Object的子類。
3. 子類方法的訪問權限必須【大於等於】父類方法的權限修飾符。
- tips:public > protected > (default) > private 備註:(default)不是關鍵字default,而是什麼都不寫,留空。
重寫的應用
子類可以根據需要,定義特定於自己的行爲。既沿襲了父類的功能名稱,又根據子類的需要重新實現父類方法,從 而進行擴展增強。設計原則:對於已經投入使用的類,儘量不要修改,推薦一個新的類,來重複利用其中共性內容,添加新的內容。
代碼舉例
定義老款手機類
package demo06;
// 本來的老款手機
public class Phone {
public void call() {
System.out.println("打電話");
}
public void send() {
System.out.println("發短信");
}
public void show() {
System.out.println("顯示號碼");
}
}
定義新款手機類,方法覆蓋重寫應用。
package demo06;
// 定義一個新手機,使用老手機作爲父類
public class NewPhone extends Phone {
//重寫父類的來電顯示號碼功能,並增加自己的顯示姓名和圖片功能
@Override
public void show() {
//調用父類已經存在的功能使用super
super.show();
//增加自己特有顯示姓名和圖片功System.out.println("顯示來電姓名");
System.out.println("顯示頭像");
}
}
定義測試類
package demo06;
public class Demo01Phone {
public static void main(String[] args) {
// 創建子類對象
NewPhone np = new NewPhone();
// 調用子類重寫的方法
np.show();
}
}
代碼運行之後結果
繼承關係中父子類構造方法的訪問特點
- 構造方法的名字是與類名一致的。所以子類是無法繼承父類構造方法的。
- 子類構造方法當中有一個默認隱含的“super()”調用,所以一定是先調用的父類構造,後執行的子類構造方法
- 子類構造可以通過super關鍵字來調用父類重載構造。
- super的父類構造調用,必須是子類構造方法的第一個語句。不能一個子類構造調用多次super構造。
- 總結:子類構造方法必須調用父類構造方法,不寫則贈送super();寫了則用寫的指定的super調用,super只能有一個,還必須是第一個。
父類空間優先於子類對象產生
在每次創建子類對象時,先初始化父類空間,再創建其子類對象本身。目的在於子類對象中包含了其對應的父類空 間,便可以包含其父類的成員,如果父類成員非private修飾,則子類可以隨意使用父類成員。代碼體現在子類的構造方法調用時,一定先調用父類的構造方法。
繼承的特點
Java只支持單繼承,不支持多繼承。
//一個類只能有一個父類,不可以有多個父類。
class C extends A{} //ok
class C extends A,B... //error
Java支持多層繼承(繼承體系)。
class A{}
class B extends A{}
class C extends B{}
子類和父類是一種相對的概念。tips:頂層父類是Object類。所有的類默認繼承Object,作爲父類。