(四)面向對象:
5、繼承:
(1)理解:
? ? ? ? 概念:
? ? ? ? ? ? ? ? 繼承是面向對象的三大特征之一
? ? ? ? ? ? ? ? 繼承是類與類之間關系的一種(是父類與子類的關系)
????????使用場景:
? ? ? ? ? ? ? ? 一個類與另一個類之間存在is a 的關系,這兩個類他們有相似的屬性和行為,那這個類就可以繼承另一個類。
? ? ? ? ? ? ? ? eg:例如,蛇繼承了爬行動物,爬行動物繼承了動物,我們就可以描述:蛇 is a 爬行動物,爬行動物是動物中的一種。
? ? ? ? 使用帶來的優點:
????????????????①提高代碼的復用性,子類繼承父類后,可以直接使用父類中非私有的屬性與方法
????????????????②提高了代碼的可維護性,只要修改父類,子類就可以全部生效
????????????????③提高了代碼的可拓展性,子類繼承父類,在子類中定義自己特有的方法,拓展功能
????????????????④是多態的前提
? ? ? ? 缺點:
????????????????①繼承讓代碼與代碼之間有了關系,耦合度上升
????????????????②父親修改后,子類不得不跟著變化,削弱了子類的獨立性,降低了代碼的靈活性
(2)繼承的實現與特點:
? ? ? ? 實現:
? ? ? ? ? ? ? ? ?①使用extends關鍵字
? ? ? ? ? ? ? ? ?②格式:[ public ] class 子類名 extends 父類名{
????????????????????????????????}
? ? ? ? ? ? ? ? ?③相關名詞:父類又稱基類,超類;子類又稱泛生類。
案例展示:
//定義Person類,作為父類
class Person {private String name;public void setName(String name) {this.name = name;}public void sayHello() {System.out.println("hello~ I am " + name);}
}//定義Student類,作為子類繼承Person
class Student extends Person {// 新增內容可以為空
}//測試類
public class Test{// 測試代碼public static void main(String[] args) {// 實例化一個子類對象Student stu = new Student();// setName方法從父類中繼承而來stu.setName("tom");// sayHello方法從父類中繼承而來stu.sayHello();}
}
? ? ? ? 特點:
? ? ? ? Java只支持單繼承,不支持多繼承。即一個類只能繼承一個類,不能同時繼承兩個父類。
? ? ? ? Java支持多層繼承,即a類繼承b類,b類繼承c類。
? ? ? ? 如果一個類沒有顯式繼承另外一個類,則默認繼承Object類
補充:1、Java支持多實現,即一個類可以實現多個接口;
? ? ? ? ? ?2、Object類(這里簡單介紹方法的作用,至于具體用法,大家可以適當拓展)
clone():
? ? ? ? 有返回值,是Object類型
? ? ? ? 不會改變原對象
? ? ? ? 用處:創建該對象的一個副本,并返回
----------------------------------------------------------
equals():
? ? ? ? 有返回值,為boolean型
? ? ? ? 不會改變原對象
? ? ? ? 用處:用于判斷兩個對象是否相等,其實比較的是兩個對象的引用地址值,想要對內容進行比較,需要重寫方法
-----------------------------------------------------------
getClass():
? ? ? ? 有返回值,返回此對象的運行時類名
? ? ? ? 不會改變原對象
? ? ? ? 用處:返回對象的運行時類
-----------------------------------------------------------
hashCode():
? ? ? ? 有返回值,返回int型
? ? ? ? 不會改變原對象
? ? ? ? 用處:返回對象的哈希碼,幫助在哈希表中快速定位對象的位置。默認實現是根據對象的引用地址計算哈希碼
-----------------------------------------------------------
toString():
? ? ? ? 有返回值,為String類型
? ? ? ? 不會改變原對象
? ? ? ? 用處:返回對象的字符串表示形式,默認實現形式為:類名@哈希碼的十六進制
? ? ? ? 注意事項:
? ? ? ? 子類只能繼承父類所有的非私有的成員
(private不能直接使用子類,如果父類中有共有的方法控制這個屬性,那子類可以控制。)
案例展示,增加理解:
父類Animal.java
//提供父類
public class Animal {//成員一個私有,一個公有private String color;public int age;//提供get|set方法public String getColor() {return color;}public void setColor(String color) {this.color = color;}public int getAge() {System.out.println("in Animal getAge() ...");return age;}public void setAge(int age) {this.age = age;}
}
子類Dog.java
//定義Dog子類 繼承 Animal
public class Dog extends Animal {// 父類中的private成員,子類中不可以直接操作(無直接訪問權限)// Animal: private String color;// 父類中的非private成員,子類中可以直接操作// Animal: public int age;// 子類新增屬性private String name;// 子類新增get|set方法public void setName(String name) {this.name = name;}public String getName() {return name;}// 子類新增方法:輸出子類對象所有屬性(含新增屬性、從父類繼承)public void disp() {// 子類方法中 不能直接操作 父類private成員// System.out.println("繼承 color: " + color); error// 子類方法中 可以間接操作(借助public的get|set) 父類private成員System.out.println("繼承 color: " + getColor());// 子類方法中 可以直接操作 父類非private成員System.out.println("繼承 age: " + age);System.out.print("新增:" + name);}
}
測試類:
public class Test0204_AccessMember {public static void main(String[] args) {Animal a = new Animal();a.setColor("black");a.setAge(3);a.show();System.out.println("------------");Dog d = new Dog();//子類對象調用從父類繼承的public方法d.setColor("yellow");d.setAge(2);//子類對象調用新增的方法d.setName("虎子");d.disp();}
}
? ? ? ? 內存結構:
(3)super關鍵字:
????????定義:
? ? ? ? ? ? ? ? 與this相似,this表示自己;super表示父類,可以理解為父類對象的引用
????????變量訪問優先級:
????????????????1. 先在子類局部范圍中找局部變量? ? ??
????????????????2. 再在子類新增的范圍中查找
????????????????3. 最后從父類繼承的成員范圍中查找
(4)構造方法的繼承:
? ? ? ? 用處:
? ? ? ? ? ? ? ? 子類對象初始化,要借助父類的構造方法,對父類部分成員進行初始化
????????注意:
? ? ? ? ? ? ? ? 子類構造方法使用前,會優先找到父類的構造方法調用,默認調用父類的無參構造,對父類繼承部分成員進行初始化,父類初始化后,在調用子類的構造代碼。
? ? ? ? ? ? ? ? 子類可以通過super(參數),顯式調用父類的構造器,但注意必須放在構造方法中的第一行,注釋除外,由于this()也要放在第一行,因此他們不能同時使用
? ? ? ? ? ? ? ? ?顯式調用父類的構造器后,就不會再默認調用父類的無參構造了
? ? ? ? ? ? ? ? ?顯式調用的父類的構造方法,父類中必須定義了
(5)靜態成員(屬性與方法)的繼承:
? ? ? ? 子類可以繼承父類的靜態成員,但不能重寫