天天看點

JAVA基礎再回首(六)——父與子的繼承、super關鍵字、方法重寫、方法重載JAVA基礎再回首(六)——父與子的繼承、super關鍵字、方法重寫、方法重載

JAVA基礎再回首(六)——父與子的繼承、super關鍵字、方法重寫、方法重載

不墨迹,才是時間管理的最大利器,學無止境。

繼承

首先我們來學習繼承的概述
  • 多個類中存在相同屬性和行為時,将這些内容抽取到單獨一個類中,那麼多個類無需再定義這些屬性和行為,隻要繼承那個類即可。
  • 通過extends關鍵字可以實作類與類的繼承
    • 格式:class 子類名 extends 父類名 {}
  • 單獨的這個類稱為父類,基類或者超類;這多個類可以稱為子類或者派生類。
  • 有了繼承以後,我們定義一個類的時候,可以在一個已經存在的類的基礎上,還可以定義自己的新成員。
以前我們沒有學習繼承之前,是這樣定義一個類和類中的方法的。
//使用繼承前
class Student {
    public void eat() {
        System.out.println("吃飯");
    }
    public void sleep() {
        System.out.println("睡覺");
    }
}

class Teacher {
    public void eat() {
        System.out.println("吃飯");
    }
    public void sleep() {
        System.out.println("睡覺");
    }
}
           
通過觀察我們可以學生類和老師類他們都有共同的方法就是吃和睡,既然老司機已經帶我們上路了,那麼我們就可以改進上面的代碼,将相同的成員抽取到一個類中,争取早日成為一名老司機。
//使用繼承後
//首先我們定義一個人類,因為老師、學生都屬于人,都要吃飯和睡覺
class Person {
    public void eat() {
        System.out.println("吃飯");
    }
    public void sleep() {
        System.out.println("睡覺");
    }
}
class Student extends Person {}

class Teacher extends Person {}

public class ExtendsDemo {
    public static void main(String[] args) {
        Student s = new Student();
        s.eat();
        s.sleep();
        System.out.println("-------------");
        Teacher t = new Teacher();
        t.eat();
        t.sleep();
    }
}
           

作為小司機可以看到使用繼承前後的輸出結果相同

運用了繼承後,我們可以看到繼承的好處也就是優點。

  • 提高了代碼的複用性
    • 多個類相同的成員可以放到同一個類中
  • 提高了代碼的維護性
    • 如果功能的代碼需要修改,修改一處即可
  • 讓類與類之間産生了關系,是多态的前提
當然運用了繼承後,他也是存在弊端的
  • 類的耦合性很強

    設計原則: 高内聚低耦合。

    簡單的了解:

    内聚就是自己完成某件事情的能力。

    耦合就是類與類之間的關系。

    我們在設計的時候原則是:自己能完成的就不麻煩别人,這樣将來别人産生了修改,就對我的影響較小。

    由此可見:在開發中使用繼承其實是在使用一把雙刃劍。今天我們還是以繼承的好處來使用,因為繼承還有很多其他的特性。

我們了解了繼承的概述,繼續了解Java中繼承的特點

  • Java隻支援單繼承,不支援多繼承。
    • 一個類隻能有一個父類,不可以有多個父類。
    • class SubDemo extends Demo{} //ok
    • class SubDemo extends Demo1,Demo2…//error
  • Java支援多層繼承(繼承體系)
    • class A{}
    • class B extends A{}
    • class C extends B{}

我們一起寫個小Demo驗證繼承的特點!

//Java隻支援單繼承,不支援多繼承。
class Father {}
class Mother {}
class Son exnteds Father {} //正确的
class Son extends Father,Mother {} // 錯誤的

//Java支援多層繼承
class GrandFather {
    public void show() {
        System.out.println("我是爺爺");
    }
}
class Father extends GrandFather {
    public void method(){
        System.out.println("我是老子");
    }
}
class Son extends Father {}
class ExtendsDemo2 {
    public static void main(String[] args) {
        Son s = new Son();
        s.method(); //使用父親的
        s.show(); //使用爺爺的
    }
}
           
那麼,在Java中繼承的注意事項有哪些呢?
  • 子類隻能繼承父類所有非私有的成員(成員方法和成員變量)
    • 其實這也展現了繼承的另一個弊端:打破了封裝性
  • 子類不能繼承父類的構造方法,但是可以通過super關鍵字去通路父類構造方法。
  • 不要為了部分功能而去繼承
  • 我們到底在什麼時候使用繼承呢?
    • 繼承中類之間展現的是:”is a”的關系。
    • 舉例:水果和蘋果,蘋果是一種水果。
    • 學生和人,學生是人的一種。
    • 是以我們總結采用假設法。如果有兩個類A,B。隻有他們符合A是B的一種,或者B是A的一種,就可以考慮使用繼承。
class Father {
        private int num = ;
        public int num2 = ;

        //私有方法,子類不能繼承
        private void method() {
            System.out.println(num);
            System.out.println(num2);
        }

        public void show() {
            System.out.println(num);
            System.out.println(num2);
        }
    }
    class Son extends Father {
        public void function() {
            //num可以在Father中通路private
            //System.out.println(num); //子類不能繼承父類的私有成員變量
            System.out.println(num2);
        }
    }
public class ExtendsDemo {

    public static void main(String[] args) {
        // 建立對象
                Son s = new Son();
                //s.method(); //子類不能繼承父類的私有成員方法
                s.show();
                s.function();
    }
}
           

輸出結果:

10

20

20

繼承中成員變量的關系

  • A:子類中的成員變量和父類中的成員變量名稱不一樣,這個太簡單。
  • B:子類中的成員變量和父類中的成員變量名稱一樣,這個怎麼玩呢?
    • 結論在子類方法中通路一個變量的查找順序:
      • a:在子類方法的局部範圍找,有就使用
      • b:在子類的成員範圍找,有就使用
      • c:在父類的成員範圍找,有就使用
      • d:如果還找不到,就報錯。
class Father {
    public int num = ;

    public void method() {
        int num = ;
    }
}

class Son extends Father {
    public int num2 = ;
    public int num = ;

    public void show() {
        int num = ;
        System.out.println(num);
        System.out.println(num2);
        // 找不到符号,報錯
        //System.out.println(num3);
    }
}
public class ExtendsDemo {

    public static void main(String[] args) {
                // 建立對象
                Son s = new Son();
                s.show();   
    }
}
           
輸出結果:
JAVA基礎再回首(六)——父與子的繼承、super關鍵字、方法重寫、方法重載JAVA基礎再回首(六)——父與子的繼承、super關鍵字、方法重寫、方法重載

記住上面的結論,到哪裡都不會出錯的

下面來學習super關鍵字

super關鍵字

  • super的用法和this很像
    • this代表本類對應的引用。
    • super代表父類存儲空間的辨別(可以了解為父類引用,可以操作父類的成員)
  • 用法(this和super均可如下使用)
    • 通路成員變量
      • this.成員變量 調用本類的成員變量
      • super.成員變量 調用父類的成員變量
  • 通路構造方法
    • this(…) 調用本類的構造方法
    • super(…) 調用父類的構造方法
  • 通路成員方法
    • this.成員方法() 調用本類的成員方法
    • super.成員方法() 調用父類的成員方法
class Father {
    public int num = ;
}

class Son extends Father {
    public int num = ;

    public void show() {
        int num = ;
        System.out.println(num);
        System.out.println(this.num);
        System.out.println(super.num);
    }
}

public class ExtendsDemo{
    public static void main(String[] args) {
        Son s = new Son();
        s.show();
    }
}
           
輸出結果:
JAVA基礎再回首(六)——父與子的繼承、super關鍵字、方法重寫、方法重載JAVA基礎再回首(六)——父與子的繼承、super關鍵字、方法重寫、方法重載

繼承中構造方法的關系

  • 子類中所有的構造方法預設都會通路父類中空參數的構造方法
    • 因為子類會繼承父類中的資料,可能還會使用父類的資料。是以,子類初始化之前,一定要先完成父類資料的初始化。
    • 注意:子類每一個構造方法的第一條語句預設都是:super();
class Father {
    int age;

    public Father() {
        System.out.println("Father的無參構造方法");
    }

    public Father(String name) {
        System.out.println("Father的帶參構造方法");
    }
}
class Son extends Father {
    public Son() {
        //super();
        System.out.println("Son的無參構造方法");
    }

    public Son(String name) {
        //super();
        System.out.println("Son的帶參構造方法");
    }
}   

public class ExtendsDemo {
    public static void main(String[] args) {
        //建立對象
        Son s = new Son();
        System.out.println("------------");
        Son s2 = new Son("寶寶");
    }
}
           
輸出結果:
JAVA基礎再回首(六)——父與子的繼承、super關鍵字、方法重寫、方法重載JAVA基礎再回首(六)——父與子的繼承、super關鍵字、方法重寫、方法重載

如果父類沒有無參構造方法,那麼子類的構造方法會出現什麼現象呢?我注釋了上面例子中父類的無參構造,然後項目報錯了,那麼我們怎麼解決呢?

  1. 在父類中加一個無參構造方法
  2. 通過使用super關鍵字去顯示的調用父類的帶參構造方法
  3. 子類通過this去調用本類的其他構造方法
  4. (子類中一定要有一個去通路了父類的構造方法,否則父類資料就沒有初始化。)
  5. 注意事項:
  6. this(…)或者super(…)必須出現在第一條語句上。
  7. 如果不是放在第一條語句上,就可能對父類的資料進行了多次初始化,是以必須放在第一條語句上。

上面說了這麼多,不知道你是否了解了,我們通過Demo再來學習

class Father {
    int age;

    /*public Father() {
        System.out.println("Father的無參構造方法");
    }*/

    public Father(String name) {
        System.out.println("Father的帶參構造方法");
    }
}
class Son extends Father {
    public Son() {
        super("111");
        System.out.println("Son的無參構造方法");
//      super("111");
    }

    public Son(String name) {
//      super("222");
        this();
        System.out.println("Son的帶參構造方法");
    }
}
public class ExtendsDemo {

    public static void main(String[] args) {
                //建立對象
                Son s = new Son();
                System.out.println("------------");
                Son s2 = new Son("寶寶");
    }
}
           
輸出結果:不知道你通過上面的概念是否能觀察出結果呢,不能的話就要去多想多練多了解
JAVA基礎再回首(六)——父與子的繼承、super關鍵字、方法重寫、方法重載JAVA基礎再回首(六)——父與子的繼承、super關鍵字、方法重寫、方法重載

繼承中成員方法的關系:

  • A:子類中的方法和父類中的方法聲明不一樣,這個太簡單。
  • B:子類中的方法和父類中的方法聲明一樣,這個該怎麼玩呢?
    • 通過子類對象調用方法:
      • a:先找子類中,看有沒有這個方法,有就使用,沒有就在父類中找
      • b:再看父類中,有沒有這個方法,有就使用
      • c:如果沒有就報錯。

方法重寫、方法重載

  • 方法重寫概述
    • 子類中出現了和父類中一模一樣的方法聲明,也被稱為方法覆寫,方法複寫。
  • 方法重載概述
    • 本類中出現的方法名一樣,參數清單不同的方法。與傳回值無關。
  • 使用特點:
    • 如果方法名不同,就調用對應的方法
    • 如果方法名相同,最終使用的是子類自己的
  • 方法重寫的應用:
    • 當子類需要父類的功能,而功能主體子類有自己特有内容時,可以重寫父類中的方法,這樣,即沿襲了父類的功能,又定義了子類特有的内容。
class Phone {
    public void call(String name) {
        System.out.println("給"+name+"打電話");
    }
}
class NewPhone extends Phone {
    public void call(String name) {
        super.call(name);
        System.out.println("打完電話了,我要聽首歌");
    }
}
public class ExtendsDemo {

    public static void main(String[] args) {
        NewPhone np = new NewPhone();
        np.call("老闆");
    }
}
           
輸出結果:
JAVA基礎再回首(六)——父與子的繼承、super關鍵字、方法重寫、方法重載JAVA基礎再回首(六)——父與子的繼承、super關鍵字、方法重寫、方法重載
上面的Demo中,手機打電話功能,是手機本身就具備的最基本的功能。是以,新手機是不用在提供這個功能的。由于它繼承了手機類,是以,我們就直接使用父類的功能即可。通過super關鍵字調用
  • 方法重寫的注意事項
    • A:父類中私有方法不能被重寫(因為父類私有方法子類根本就無法繼承)
    • B:子類重寫父類方法時(通路權限不能更低,最好就一緻)
    • C:父類靜态方法,子類也必須通過靜态方法進行重寫
    • 子類重寫父類方法的時候,最好聲明一模一樣。
我們一起來做兩個經典例題
  • 方法重寫(Override)和方法重載(Overload)的差別?方法重載能改變傳回值類型嗎?

    方法重寫:在子類中,出現和父類中一模一樣的方法聲明的現象。

    方法重載:同一個類中,出現的方法名相同,參數清單不同的現象。

    方法重載能改變傳回值類型,因為它和傳回值類型無關。

  • this關鍵字和super關鍵字分别代表什麼?以及他們各自的使用場景和作用。

    this:代表目前類的對象引用

    super:代表父類存儲空間的辨別。(可以了解為父類的引用,通過這個東西可以通路父類的成員)

    場景:

    成員變量:this.成員變量——super.成員變量

    構造方法:this(…)——super(…)

    成員方法:this.成員方法——super.成員方法

好了,今天我們學了這麼多,要好好消化一下,做到學以緻用。最後送大家一句話。

不管有多苦,千萬要記住:苦難是我們人生路上不可缺少的經曆,隻有活着,才有幸福的可能!