一、什么是繼承?
在學(xué)習(xí)之前,我們先要了解一下什么叫繼承,簡(jiǎn)單點(diǎn)講就是:
在很多個(gè)類中存在相同屬性和行為時(shí),把這些相同內(nèi)容以及相同屬性單獨(dú)抽取到一個(gè)類中,那這些類就不用重新定義這些屬性和行為,只要繼承那個(gè)類就好了。
很多個(gè)類可以稱之為子類,單獨(dú)的這個(gè)類可以稱之為父類、超類或者基類。子類呢,可以直接訪問(wèn)父類中的非私有的屬性以及行為。也可以通過(guò) extends 關(guān)鍵字讓類與類之間產(chǎn)生繼承關(guān)系。這樣聽懂了嗎?是不是很簡(jiǎn)單,我們通過(guò)案例來(lái)進(jìn)一步了解~
class Dog extends Animal
//Dog 是子類 //Animal是父類
二、那為什么要繼承呢?
2.1 繼承的方式
當(dāng)多個(gè)類存在相同的屬性以及方法的時(shí)候,每次都需要描述時(shí),都需要寫一遍,這樣代碼的冗余率很高,也很浪費(fèi)效率,但是如果能夠有一個(gè)繼承機(jī)制,我們就能夠把這些相同的屬性和方法給它抽調(diào)出來(lái),書寫成一個(gè)父類,當(dāng)子類需要的時(shí)候,直接繼承就好了,不需要在對(duì)這部分進(jìn)行書寫,只需要進(jìn)行補(bǔ)充就好啦。效率就大大提高了~
代碼如下(示例):
class Animal {
public String name;
public int age;
public void eat() {
System.out.println(name+"正在吃飯! ");
}
}
class Dog extends Animal {
public void bark() {
System.out.println(name+"汪汪叫! ");
}
}
class Cat extends Animal {
public void mew() {
System.out.println(name+"喵喵叫! ");
}
}
咱們這里是用動(dòng)物來(lái)舉例子,生活中最常見的就是貓貓和狗,貓貓和狗狗的特性一般都有,咱們會(huì)給它們?nèi)∶郑€有年齡,同時(shí)也吃東西等等這些共性,當(dāng)然還有很多相同之點(diǎn),就不一個(gè)一個(gè)舉例了。我們可以將這些共性呢,寫成一個(gè)Animal類,直接繼承,然后寫入特有的bark和mew方法即可:
繼承的優(yōu)點(diǎn):
1.提高代碼的復(fù)用性。
2.讓類與類之間產(chǎn)生了關(guān)系,是多態(tài)的前提。
2.2 繼承的特點(diǎn)
1.JAVA只支持單繼承,不支持多繼承。
2.Java支持多層(重)繼承(繼承體系)。
3.繼承關(guān)系一般不希望超過(guò)三層,如果超過(guò)那么就考慮重構(gòu)了.
三、繼承后如何訪問(wèn)?
3.1訪問(wèn)父類成員變量
代碼如下(示例)
//不存在同名的情況
class Father {
int a;
int b;
}
class Son extends Father {
int c;
public void func() {
a = 10;
b = 20;
c = 30;
}
}
在這里a,b直接訪問(wèn)的時(shí)父類繼承下來(lái)的a,b,能夠直接進(jìn)行賦值
//父類和子類成員變量同名
class Father {
int a;
int b;
}
class Son extends Father {
int a;
int b;
int c;
public void func() {
a = 10;
b = 20;
c = 30;
}
}
在這里a,b訪問(wèn)的是子類中的a,b
總結(jié):
1.如果訪問(wèn)的成員變量如果子類有,優(yōu)先訪問(wèn)子類的。
2.如果子類中無(wú),則訪問(wèn)父類中的,如果父類也沒有,則編譯失敗.
3.如果訪問(wèn)子類父類中都有,則優(yōu)先訪問(wèn)子類的,采用的就是一個(gè)就近原則
3.2訪問(wèn)父類成員方法
//父類子類成員方法名不同
class Father {
public void func1() {
System.out.println("func1");
}
}
class Son extends Father {
public void func2() {
System.out.println("func2");
}
public void func3() {
func1();
func2();
}
}
在func3()中訪問(wèn)的func1()是父類的func1()
class Father {
public void func1() {
System.out.println("Father: func1");
}
}
class Son extends Father {
public void func1() {
System.out.println("Son: func1");
}
public void func2() {
System.out.println("Son: func2");
}
public void func3() {
func1();
func2();
}
}
在func3()中訪問(wèn)的func1()是子類的func1()
總結(jié):
1.子類與父類方法名不同時(shí),優(yōu)先在子類找,如果子類找不到,則去父類找,如果父類找不到,則編譯錯(cuò)誤。
2.子類與父類同名方法時(shí),如果父類和子類同名方法的參數(shù)不同,則根據(jù)調(diào)用選擇合適的參數(shù)進(jìn)行訪問(wèn),如果沒有合適的則報(bào)錯(cuò)誤.
四、super的使用
如果子類中存在與父類中相同的成員時(shí),那如何在子類中訪問(wèn)父類相同名稱的成員呢?
可以使用super關(guān)鍵字進(jìn)行訪問(wèn).
4.1 訪問(wèn)父類的成員
class Father {
int a;
int b;
}
class Son extends Father {
int a;
int b;
int c;
public void func() {
super.a = 10;
super.b = 20;
c = 30;
}
}
4.2 訪問(wèn)父類的方法
class Father {
public void func1() {
System.out.println("Father: func1");
}
}
class Son extends Father {
public void func1() {
System.out.println("Son: func1");
}
public void func2() {
System.out.println("Son: func2");
}
public void func3() {
super.func1();
func2();
}
}
注意:
1.super只能在非靜態(tài)方法中使用
2.在子類方法中,訪問(wèn)父類的成員變量和方法
4.3 子類構(gòu)造方法
在生成子類對(duì)象時(shí),會(huì)先調(diào)用父類的構(gòu)造方法,在去執(zhí)行子類的構(gòu)造方法.一般沒有寫出來(lái),系統(tǒng)會(huì)默認(rèn)寫入.
class Father {
public Father() {
System.out.println("Father!");
}
}
class Son extends Father {
public Son() {
//super();
System.out.println("Son!");
}
public static void main(String[] args) {
Son son = new Son();
}
}
這里驗(yàn)證了我們所說(shuō)的,在實(shí)例子類對(duì)象時(shí),會(huì)先調(diào)用父類的實(shí)例方法,然后在調(diào)用我們子類的實(shí)例方法,在子類的構(gòu)造方法默認(rèn)有一個(gè)super()方法去調(diào)用父類的構(gòu)造方法,如果我們自己寫的父類的構(gòu)造方法是帶參數(shù)的,我們但自己在子類構(gòu)造方法第一行寫super(參數(shù))不然會(huì)編譯報(bào)錯(cuò).
4.4 super和this
1.super是一個(gè)關(guān)鍵字,代表父類的存儲(chǔ)空間標(biāo)識(shí)。(可以理解為父親的引用)
2.super和this的用法相似。
3.this代表對(duì)象的引用(誰(shuí)調(diào)用就代表誰(shuí));
4.super代表當(dāng)前子類對(duì)父類的引用。
5.super();和this();都是在構(gòu)造函數(shù)的第一行,不能同時(shí)出現(xiàn)。
不同點(diǎn)
1.成員變量
this.變量 本類的
super.變量 父類的
2.構(gòu)造方法
this(...) 本類的
super(...) 父類的
3.成員方法
this.方法名() 本類的
super.方法名() 父類的
4.5 繼承代碼塊執(zhí)行順序
1.父類靜態(tài)代碼塊優(yōu)先執(zhí)行,然后子類靜態(tài)代碼塊執(zhí)行,靜態(tài)代碼塊只執(zhí)行一次
2.在實(shí)例子類對(duì)象時(shí),父類實(shí)例代碼塊和父類構(gòu)造方法緊接著執(zhí)行.
3.子類的實(shí)例代碼塊和子類構(gòu)造方法再執(zhí)行
五、組合
5.1 final關(guān)鍵字
1.final修飾變量表示常量,不能再修改(常量書寫默認(rèn)為單詞的大寫)
final int COUNT = 0;
COUNT = 10;//編譯錯(cuò)誤
2.final修飾類表示該類不能在被繼承
final class Father {
}
class Son extends Father {
}
3.final修飾的方法不能夠重寫
5.2 組合
組合表示的是:對(duì)象之間存在has的關(guān)系,其中一個(gè)類是其他幾個(gè)類的組合.
class Tire {
}
class Engine {
}
class VehicleSystem {
}
class Car {
private Tire tire;
private Engine engine;
private VehicleSystem vehicleSystem;
}
class Ferrari extends Car {
}
今天這篇文章就先寫到這里啦,喜歡的話,可以點(diǎn)贊,關(guān)注+評(píng)論,同時(shí)呢,也可以轉(zhuǎn)發(fā)一下,讓更多的朋友看到~~