繼承、重載、重寫和子類實例化

1、繼承

(1)當多個類中存在相同的屬性和行爲時,將這些內容抽取到單獨的一個類中,那麼多個類無需再定義這些屬性和行爲,只要繼承那個類即可。
(2)多個類稱爲子類,被繼承的單獨的類稱爲父類或超類。
(3)子類可以直接訪問父類中的非私有屬性行爲
(4)通過extends 關鍵字使類和類之間產生繼承關係。
見示例:
//繼承、instanceof的用法、對象類型的強制類型轉換
public class ExtendsDemo {
    public static void main(String[] args){
        Student s = new Student("張三",23);
        Teacher t = new Teacher("李四",35);
        Print(s);
        Print(t);
    }
    private static void Print(Person p){
        if(p instanceof Student){        //instanceof 關鍵字用來判斷一個實例是否是某一類型,是返回true,否返回false。
            Student s = (Student) p;     //這裏必須使用類型轉換,Person()類中沒有 learn()方法,強制轉型爲 Student類型,才能調用learn()
            System.out.print(s.name+" "+s.age+" "+s.eat()+" ");
            s.learn();
        }
        else if(p instanceof Teacher){
            Teacher t = (Teacher) p;
            System.out.print(t.name+" "+t.age+" "+t.eat()+" ");
            t.teach();
        }
        else{ System.out.println("error");}
    }
}
class Person{
    public String name;
    public int age;
    public String eat(){
        return "吃飯";
    }
}
class Student extends Person{        //extends 關鍵字表示繼承關係
    Student(String name,int age){
        this.name = name;
        this.age = age;
    }
    public void learn(){
        System.out.println("學習");
    }
}
class Teacher extends Person{
    Teacher(String name,int age){
        this.name = name;
        this.age = age;
    }
    public void teach(){
        System.out.println("教課");
    }
}
學生跟老師都有姓名和年齡這兩個屬性,都有吃東西這個行爲。
所以把這兩個屬性和一個行爲抽取出來,封裝到一個單獨的 Person() 類中。
Student() 類和 Teacher() 類再使用 extends 關鍵字繼承 Person() 類的成員變量和成員函數。
主函數的 Print()方法中,因爲傳遞的參數是 Person 父類,當用instanceof 關鍵字判斷實例是否是 Student類型後,要用強制類型轉換,從 Person類型強制轉換爲 Student類型,才能調用 Student類型的 Learn()方法。

Java只支持單繼承,就是一個子類只能有一個父類,不支持多繼承,但在類與接口間支持多實現

2、重載

重載函數是函數的一種特殊情況,爲方便使用,允許在同一範圍中聲明幾個功能類似的同名函數,但是這些同名函數的形式參數(指參數的個數、類型或者順序)必須不同,也就是說用同一個運算符完成不同的運算功能。這就是重載函數。重載函數常用來實現功能類似而所處理的數據類型不同的問題。
兩個重載函數必須在下列一個或兩個方面有所區別:(只看參數)
1.、函數有不同參數。
2、函數有不同參數類型,


3、函數覆蓋/重寫(OverRide)

(1)子類中出現與父類一模一樣的方法時,會出現覆蓋操作,也稱爲重寫或者複寫。
(2)父類中的私有方法不可以被覆蓋。
(3)在子類覆蓋方法中,繼續使用被覆蓋的方法可以通過super.函數名獲取。

覆蓋注意事項:
(1)覆蓋時,子類方法權限一定要大於等於父類方法權限
(2)靜態只能覆蓋靜態
覆蓋的應用:當子類需要父類的功能,而功能主體子類有自己特有內容時,可以複寫父類中的方法,這樣,即沿襲了父類的功能,又定義了子類特有的內容。
//輸出結果爲“吃蘋果 吃西瓜”
public class OverRideDemo{
    public static void main(String[] args){
        Student s = new Student();
        s.eat();
        s.eat_2();
    }
}
class Person{
    public void eat(){
        System.out.println("吃西瓜");
    }
}
class Student extends Person{
    public void eat(){
        System.out.println("吃蘋果");
    }
    public void eat_2(){
        super.eat();  //使用 super.函數名() 來調用父類的函數
    }
}

4、子類的實例化過程

對象的初始化:
(1)
靜態代碼塊隨着類的加載最先初始化。
(2)默認初始化。
(3)構造代碼塊初始化。
(4)構造函數初始化。
Person p = new Person();
/**
因爲new用到了Person.class 所以會先找到Person.class 文件並加載到內存中。
執行該類中的static代碼塊,如果有的話,給Person.class 類進行初始化。
在堆內存中開闢空間,分配內存地址。
在堆內存中建立對象的特有屬性,並進行默認初始化。
對屬性進行顯示初始化。
對對象進行構造代碼塊初始化。
對對象進行對應的構造函數初始化。
將內存地址賦給棧內存中的p 變量。
*/

子類的實例化:
(1)子類的實例創建時,會先默認訪問父類中空參的構造函數,因爲子類初始化要首先初始化父類。
(2)子類中,每一個構造函數的第一行都有一條默認的語句 super(); 
(3)子類會具備父類中的數據,所以要先明確父類是如何對這些數據初始化的。
(4)當父類中沒有空參數的構造函數時,子類的構造函數必須通過this或者super語句指定要訪問的構造函數。
public class OverRideDemo{
    public static void main(String[] args){
        Student s = new Student();
    }
}
class Person{
    Person(){
        System.out.println("父類初始化");
    }
}
class Student extends Person{
    Student(){
        System.out.println("子類初始化");
    }
}
輸出結果爲:

這表示子類初始化時,會先初始化父類
父類中無空參構造函數時:
public class OverRideDemo{
    public static void main(String[] args){
        Student s = new Student(21);
    }
}
class Person{
    Person(int age){
        System.out.println("父類初始化 "+age);
    }
}
class Student extends Person{
    Student(int age){
        super(age);    //父類中無空參構造函數時,要指定使用哪個構造函數來初始化父類。
        System.out.println("子類初始化");
    }
}
輸出結果:



靜態代碼塊隨着類的加載最先初始化

發佈了39 篇原創文章 · 獲贊 7 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章