JAVA面向物件之繼承
面向物件之繼承
學習要點:
- 掌握繼承的優點和實現方法
- 掌握子類重寫父類的方法
- 掌握繼承條件下構造方法的執行過程
一、為什麼需要繼承
觀察兩個類:
蘋果類
public class Apple { String name; String color; String brand; public void print(){ System.out.println(brand+"牌的"+name); } }
橙子類
public class Orange {
String name;
String size;
String brand;
public void print(){
System.out.println(brand+"牌的"+name);
}
}
類圖:
我們發現,這邊兩個類,很多的屬性相同,方法也是相同的
面向物件解決的就是程式碼重複的問題
上面的String name、String brand重複了,我們就應該抽取出來
我們的程式碼可以複用,不能重複。
怎麼解決呢?---->繼承
看類圖
將我們覺得共有的屬性提取出來,另找一張圖紙使Apple與Fruit產生關係
呼叫的時候將Apple和Fruit看成一張圖紙即可
二、繼承是啥
簡單來說,就是將一個品種的類,相同的屬性、方法抽取出來,形成一個父類
讓子類繼承父類,那些重複的程式碼只需要在父類出現一次即可
現實意義:
- 繼承基因,繼承家產
定義:
- 繼承是面向物件最顯著的一個特性。繼承是從已有的類中派生出新的類,新的類能吸收已有類的資料屬性和行為,並能擴充套件新的能力。
王者榮耀中的角色體系
英雄是父類 --屬性:名字,性別,價格,攻擊力 行為:攻擊、防禦
子類有各個職業,比如戰士、法師、射手、刺客
戰士:一次攻擊個數 射手:攻擊距離
總結出各個子類共有的屬性,就是父類的屬性。
三、如何使用繼承
我們剛才已經學會抽取共有的屬性
現在學習
- 如何將共有的屬性編寫成父類
- 如何讓子類繼承父類
1、編寫父類
編寫父類和之前學習的編寫類,是一個玩意
我們就以一開始的水果類為模板
首先水果類
public class Fruit {
public String name;
public String brand;
//展臺展示
public void print(){
System.out.println(brand+"牌的"+name);
}
}
2、讓子類繼承父類
首先語法是:
public class [類名] extends [父類名]
使用extends關鍵字,讓子類繼承父類
就一開始的蘋果和橙子
蘋果
public class Apple extends Fruit{
String color;
}
橙子
public class Orange extends Fruit{
String size;
}
四、何時使用繼承
我們知道了為啥使用繼承,也知道了怎麼使用繼承
但是我們該在哪裡、什麼時候使用繼承呢?
條件一、有共有的屬性和方法的時候
正如剛才的兩個水果,有相同的屬性之後
我們進行了抽取,抽取出了父類
但是這樣還是條件不夠
名字和品牌,有這兩個屬性的類是不是很多啊
衣服,手機,電腦
我們該怎麼區分呢
條件二、符合is-a原則
什麼是is-a原則:
- 子類 is-a 父類
剛才的蘋果is-a水果,橙子is-a水果
滿足兩個條件的時候,就可以進行父類抽取了
條件三、一個類只能繼承一個父類
這是對類繼承的要求、不過多講解
五、理解繼承
1、刪除父類方法中,子類相關的屬性
提取過程中,對於公共方法中呼叫非公共屬性的語句,需要稍作調整
2、子類繼承了父類的哪些東西
實際上問題應該是這個:子類可以繼承父類的所有些資源嗎?
肯定是不能的。
首要的就是private修飾的屬性、方法,這個大家肯定知道私有的
第二預設的修飾符下,子類和父類不在同一個包內的情況
第三父類的構造方法
除了這三個,其他的都是可以的
為了在不同包繼承,但又不是所有類可以呼叫的情況
我們之前提過的protected就是用在這裡的
只要繼承就能繼承到protected修飾的方法屬性
訪問修飾符 | 本類 | 同包 | 子類 | 其他 |
---|---|---|---|---|
private | √ | |||
預設 | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
3、super關鍵字
我們知道,我們不能繼承父類的建構函式,但是很多構造在父類已經寫過了,再寫不就又程式碼重複了麼
所以java給了我們super關鍵字
當我們需要呼叫父類的構造方法的時候,需要在子類的構造方法中使用super();這是無參的,有參的加入引數即可
且必須是第一句
想呼叫個別屬性的時候使用super.[父類屬性名]的方式
想在子類中呼叫父類方法的時候也可以使用super.[父類方法名]的方式
例子:
//我們假設Fruit類的構造方法為 Fruit() Fruit(String name) 屬性為 name brand 方法為 print()
//那麼Apple類中的構造方法想呼叫就要
//在子類構造方法中呼叫且必須是第一句
//無參
public Apple(){
super();
super.brand="大品牌";
}
//有參
public Apple(String name){
super(name);
}
//方法
public void test(){
super.print();
}
-
在構造方法中,如果出現this或super關鍵字,則只能是該方法的第一條語句
-
在一個構造方法中,不允許同時使用this和super關鍵字呼叫構造方法
-
在類方法中,不允許出現this或super關鍵字
-
在例項方法中,this和super語句不要求是第一條語句,可以共存
4、方法的重寫(Overriding)
剛才的水果類中,我們想要在水果類的print()方法,輸出品牌和名字的同時,還想要輸出蘋果的顏色,橙子的大小等資訊
在父類的方法中肯定是無法實現的
這就涉及到繼承的一個特點了
就是方法的重寫
4.1、重寫的定義
-
意義:在子類中,根據需求對從父類繼承的方法體進行重新編寫,以實現子類需求
-
子類中出現與父類,方法宣告完全一樣的方法,就是重寫
-
方法名,引數列表,返回值型別都一樣,許可權修飾符不能比父類方法更弱,方法體不同
4.2、注意點
- 重寫方法和被重寫方法必須具有相同的方法名
- 重寫方法和被重寫方法必須具有相同的引數列表
- 重寫方法返回值型別必須和被重寫方法的返回值型別相同或為其子類
- 重寫方法不能縮小被重寫方法的訪問許可權
4.3、示例
public class Apple extends Fruit{
String color;
public void print(){
super.print();
System.out.println("顏色是"+color);
}
}
4.4、重寫和過載的區別
位置 | 方法名 | 引數表 | 返回值 | 訪問修飾符 | |
---|---|---|---|---|---|
方法過載 | 同類 | 相同 | 不相同 | 無關 | 無關 |
方法重寫 | 子類 | 相同 | 相同 | 相同或是其子類 | 不能比父類更嚴格 |
六、Object類
Object類是所有類的祖先
- 所有的類都直接或者間接的繼承了Object類
是在java.lang包底下的
在定義一個類時,如果沒有使用extends關鍵字,即沒有顯式地繼承某個類,那麼這個類直接繼承Object類
常用方法
方法 | 說明 |
---|---|
toString() | 返回當前物件本身的有關資訊,返回字串物件 |
equals() | 比較兩個物件是否是同一個物件。若是,返回true |
clone() | 生成當前物件的一個副本,並返回 |
hashCode() | 返回該物件的雜湊程式碼值 |
getClass() | 獲取當前物件所屬的類資訊,返回Class物件 |
java.lang.String類重寫了Object類中的equals()方法,用於比較兩個字串的值是否相等
七、練習
設計編寫王者榮耀/英雄聯盟英雄關係
要求:1、使用繼承
2、重寫方法
3、寫出父類Hero、子類戰士Fighter、射手Shooter
類圖如下