全套Java教程_Java基礎入門教程,零基礎小白自學Java必備教程 🐱# 013 # 第十三單元 繼承、super、this、抽象類 #
(Ⅰ)知識點概述
二、本單元目標
(Ⅰ)重點知識目標
1.方法重寫
2.Super和this關鍵字
3.抽象類
三、本單元知識詳講
13.1 繼承
13.1.1 繼承的由來★★★
多個類中存在相同屬性和行為時,將這些內容抽取到單獨一個類中,那麼多個類無需再定義這些屬性和行為,只要 繼承那一個類即可。如圖所示:
13.1.2 繼承的定義★★★
-
繼承:就是子類繼承父類的屬性和行為,使得子類對象具有與父類相同的屬性、相同的行為。子類可以直接 訪問父類中的非私有的屬性和行為。
13.1.3 繼承的好處★★★★
-
提高程式碼的復用性。
-
類與類之間產生了關係,是多態的前提。
13.1.4 繼承的格式★★★
通過 extends
1 class 父類 { 2 ... 3 } 4 class 子類 extends 父類 { 5 ... 6 }
繼承演示,程式碼如下:
1 /* 2 * 定義員工類Employee,做為父類 3 */ 4 class Employee { 5 String name; // 定義name屬性 6 // 定義員工的工作方法 7 public void work() { 8 System.out.println("盡心儘力地工作"); 9 } 10 } 11 12 /* 13 * 定義講師類Teacher 繼承 員工類Employee 14 */ 15 class Teacher extends Employee { 16 // 定義一個列印name的方法 17 public void printName() { 18 System.out.println("name=" + name); 19 } 20 } 21 22 /* 23 * 定義測試類 24 */ 25 public class ExtendDemo01 { 26 public static void main(String[] args) { 27 // 創建一個講師類對象 28 Teacher t = new Teacher(); 29 // 為該員工類的name屬性進行賦值 30 t.name = "小明"; 31 // 調用該員工的printName()方法 32 t.printName(); // name = 小明 33 // 調用Teacher類繼承來的work()方法 34 t.work(); // 盡心儘力地工作 35 } 36 }
13.1.5 繼承的特點 ★★★★
//一個類只能有一個父類,不可以有多個父類。 class C extends A{} //ok class C extends A,B... //error
class A{} class B extends A{} class C extends B{}
當類之間產生了關係後,其中各類中的成員變數,又產生了哪些影響呢?
1 class Fu { 2 // Fu中的成員變數。 3 int num = 5; 4 } 5 class Zi extends Fu { 6 int num2 = 6; 7 // Zi中的成員方法 8 public void show() { 9 // 訪問父類中的num, 10 System.out.println("Fu num="+num); // 繼承而來,所以直接訪問。 11 // 訪問子類中的num2 12 System.out.println("Zi num2="+num2); 13 } 14 } 15 class ExtendDemo02 { 16 public static void main(String[] args) { 17 // 創建子類對象 18 Zi z = new Zi(); 19 // 調用子類中的show方法 20 z.show(); 21 } 22 } 23 演示結果: 24 Fu num = 5 25 Zi num2 = 6
1 class Fu { 2 // Fu中的成員變數。 3 int num = 5; 4 } 5 class Zi extends Fu { 6 // Zi中的成員變數 7 int num = 6; 8 public void show() { 9 // 訪問父類中的num 10 System.out.println("Fu num=" + num); 11 // 訪問子類中的num 12 System.out.println("Zi num=" + num); 13 } 14 } 15 class ExtendsDemo03 { 16 public static void main(String[] args) { 17 // 創建子類對象 18 Zi z = new Zi(); 19 // 調用子類中的show方法 20 z.show(); 21 } 22 } 23 演示結果: 24 Fu num = 6 25 Zi num = 6
super.父類成員變數名
子類方法需要修改,程式碼如下:
1 class Zi extends Fu { 2 // Zi中的成員變數 3 int num = 6; 4 public void show() { 5 //訪問父類中的num 6 System.out.println("Fu num=" + super.num); 7 //訪問子類中的num 8 System.out.println("Zi num=" + this.num); 9 } 10 } 11 演示結果: 12 Fu num = 5 13 Zi num = 6
小貼士:Fu 類中的成員變數是非私有的,子類中可以直接訪問。若Fu 類中的成員變數私有了,子類是不能 直接訪問的。通常編碼時,我們遵循封裝的原則,使用private修飾成員變數,那麼如何訪問父類的私有成員 變數呢?對!可以在父類中提供公共的getXxx方法和setXxx方法。
當類之間產生了關係,其中各類中的成員方法,又產生了哪些影響呢?
-
成員方法不重名
如果子類父類中出現不重名的成員方法,這時的調用是沒有影響的
1 class Fu{ 2 public void show(){ 3 System.out.println("Fu類中的show方法執行"); 4 } 5 } 6 class Zi extends Fu{ 7 public void show2(){ 8 System.out.println("Zi類中的show2方法執行"); 9 } 10 } 11 public class ExtendsDemo04{ 12 public static void main(String[] args) { 13 Zi z = new Zi(); 14 //子類中沒有show方法,但是可以找到父類方法去執行 15 z.show(); 16 z.show2(); 17 } 18 }
如果子類父類中出現重名的成員方法,這時的訪問是一種特殊情況,叫做方法重寫 (Override)。
-
方法重寫 :子類中出現與父類一模一樣的方法時(返回值類型,方法名和參數列表都相同),會出現覆蓋效 果,也稱為重寫或者複寫。聲明不變,重新實現。
1 class Fu { 2 public void show() { 3 System.out.println("Fu show"); 4 } 5 } 6 7 class Zi extends Fu { 8 //子類重寫了父類的show方法 9 public void show() { 10 System.out.println("Zi show"); 11 } 12 } 13 public class ExtendsDemo05{ 14 public static void main(String[] args) { 15 Zi z = new Zi(); 16 // 子類中有show方法,只執行重寫後的show方法 17 z.show(); // Zi show 18 } 19 }
1 class Phone { 2 public void sendMessage(){ 3 System.out.println("發簡訊"); 4 } 5 6 public void call(){ 7 System.out.println("打電話"); 8 } 9 10 public void showNum(){ 11 System.out.println("來電顯示號碼"); 12 } 13 } 14 //智慧手機類 15 class NewPhone extends Phone { 16 //重寫父類的來電顯示號碼功能,並增加自己的顯示姓名和圖片功能 17 public void showNum(){ 18 //調用父類已經存在的功能使用super 19 uper.showNum(); 20 //增加自己特有顯示姓名和圖片功能 21 System.out.println("顯示來電姓名"); 22 System.out.println("顯示頭像"); 23 } 24 } 25 26 public class ExtendsDemo06 { 27 public static void main(String[] args) { 28 // 創建子類對象 29 NewPhone np = new NewPhone(); 30 // 調用父類繼承而來的方法 31 np.call(); 32 // 調用子類重寫的方法 33 np.showNum(); 34 } 35 }
小貼士:這裡重寫時,用到super.父類成員方法,表示調用父類的成員方法。
-
-
-
子類方法覆蓋父類方法,必須要保證許可權大於等於父類許可權。
-
子類方法覆蓋父類方法,返回值類型、函數名和參數列表都要一模一樣。
-
-
-
繼承後的特點——構造方法
當類之間產生了關係,其中各類中的構造方法,又產生了哪些影響呢? 首先我們要回憶兩個事情,構造方法的定義格式和作用。
-
構造方法的名字是與類名一致的。所以子類是無法繼承父類構造方法的。
-
構造方法的作用是初始化成員變數的。所以子類的初始化過程中,必須先執行父類的初始化動作。子類的構 造方法中默認有一個
super()
-
1 class Fu { 2 private int n; 3 Fu(){ 4 System.out.println("Fu()"); 5 } 6 } 7 class Zi extends Fu { 8 Zi(){ 9 // super(),調用父類構造方法 10 super(); 11 System.out.println("Zi()"); 12 } 13 } 14 public class ExtendsDemo07{ 15 public static void main (String args[]){ 16 Zi zi = new Zi(); 17 } 18 } 19 輸出結果: 20 Fu() 21 Zi()
13.2 Super和This
13.2.1 super和this的含義 ★★★
-
super :代表父類的存儲空間標識(可以理解為父親的引用)。
-
this :代表當前對象的引用(誰調用就代表誰)。
13.2.2 super和this的用法★★★★
-
訪問成員
this.成員變數 ‐‐ 本類的 super.成員變數 ‐‐ 父類的 this.成員方法名() ‐‐ 本類的 super.成員方法名() ‐‐ 父類的
用法演示,程式碼如下:
1 class Animal { 2 public void eat() { 3 System.out.println("animal : eat"); 4 } 5 } 6 class Cat extends Animal { 7 public void eat() { 8 System.out.println("cat : eat"); 9 } 10 public void eatTest() { 11 this.eat(); // this 調用本類的方法 12 super.eat(); // super 調用父類的方法 13 } 14 } 15 public class ExtendsDemo08 { 16 public static void main(String[] args) { 17 Animal a = new Animal(); 18 a.eat(); 19 Cat c = new Cat(); 20 c.eatTest(); 21 } 22 } 23 輸出結果為: 24 animal : eat 25 cat : eat 26 animal : eat
this(...) ‐‐ 本類的構造方法 super(...) ‐‐ 父類的構造方法
子類的每個構造方法中均有默認的super(),調用父類的空參構造。手動調用父類構造會覆蓋默認的super()。 super() 和 this() 都必須是在構造方法的第一行,所以不能同時出現。
13.3 抽象類
13.3.1 抽象類的由來★★
父類中的方法,被它的子類們重寫,子類各自的實現都不盡相同。那麼父類的方法聲明和方法主體,只有聲明還有 意義,而方法主體則沒有存在的意義了。我們把沒有方法主體的方法稱為抽象方法。Java語法規定,包含抽象方法 的類就是抽象類。
13.3.2 抽象類的定義★★★
-
抽象方法 : 沒有方法體的方法。
-
抽象類:包含抽象方法的類。
13.3.3 抽象方法★★★
使用 abstract 關鍵字修飾方法,該方法就成了抽象方法,抽象方法只包含一個方法名,而沒有方法體。
定義格式:
修飾符 abstract 返回值類型 方法名 (參數列表);
程式碼舉例:
public abstract void run();
如果一個類包含抽象方法,那麼該類必須是抽象類。
定義格式:
abstract class 類名字 { }
程式碼舉例:
public abstract class Animal { public abstract void run(); }
13.3.5 抽象的使用★★★
繼承抽象類的子類必須重寫父類所有的抽象方法
程式碼舉例:
1 public class Cat extends Animal { 2 public void run (){ 3 System.out.println("小貓在牆頭走~~~"); 4 } 5 } 6 7 public class CatTest { 8 public static void main(String[] args) { 9 // 創建子類對象 10 Cat c = new Cat(); 11 // 調用run方法 12 c.run(); 13 } 14 } 15 輸出結果: 16 小貓在牆頭走~~~
13.3.6 注意事項有哪些★★
關於抽象類的使用,以下為語法上要注意的細節,雖然條目較多,但若理解了抽象的本質,無需死記硬背。
-
-
理解:假設創建了抽象類的對象,調用抽象的方法,而抽象方法沒有具體的方法體,沒有意義。
-
-
抽象類中,可以有構造方法,是供子類創建對象時,初始化父類成員使用的。
-
理解:子類的構造方法中,有默認的super(),需要訪問父類構造方法。
-
-
抽象類中,不一定包含抽象方法,但是有抽象方法的類必定是抽象類。
-
理解:未包含抽象方法的抽象類,目的就是不想讓調用者創建該類對象,通常用於某些特殊的類結構設 計。
-
-
抽象類的子類,必須重寫抽象父類中所有的抽象方法,否則,編譯無法通過而報錯。除非該子類也是抽象 類。
-
理解:假設不重寫所有抽象方法,則類中可能包含抽象方法。那麼創建對象後,調用抽象的方法,沒有 意義。
-