1. 程式人生 > >Java面向物件(三)—— 繼承

Java面向物件(三)—— 繼承

標籤: java 繼承 抽象類 this super abstract


概述

多個類中存在相同的屬性和行為的時候,將這些內容抽取到單獨一個類中,那麼多個類無需在定義這些屬性和行為,只要繼承那個類即可。

  • 多個類可以稱為子類,單獨這個類稱為父類或者超類。
  • 子類可以直接訪問父類中的菲斯有的屬性和行為。
  • 通過 extends 關鍵字讓類與類之間產生繼承關係。
    • class SubDemo extends Demo{}
  • 繼承的出現提高了程式碼的複用性
  • 整合的出現讓類與類之間產生了關係,提供了多型的前提。

繼承的特點

  1. java只支援單繼承,不支援多繼承
    • 一個類只能有一個父類,不可以有過個父類
  2. java支援多層繼承(繼承體系)
  3. 定義繼承需要注意:
    • 不要僅為了獲取其他類中某個功能而去繼承
    • 類與類之間要有所屬(“is a”)關係,xx1是xx2的一種
class ClassDemo1{
    public static void main(String[] args){
        Dog d = new Dog();
        d.color = "white";//雖然在Dog類中並未定義color,但是由於繼承,並不影響賦值
        System.out.println(d.color);
        
    }
}

class Animal{
    String color;
    int weight;
}
/**
 *建立Dog類,繼承Animal
 */
class Dog extends Animal{
        
}

說道繼承,不得不說的兩個關鍵詞就是this和super

上一篇中我們說了建構函式中傳參的方式,但是如果引數是這樣的形式呢?

class ClassDemo1{
    public static void main(String[] args){  
        Dog d2 = new Dog("white");
        System.out.println(d2.color);
    }   
}

class Dog{
    //成員屬性
    public String color;
    public int age; 
    //建構函式
    //空構造
    public Dog(){
        
    }
    //只有一個引數的建構函式
    public Dog(String color){
        color = color;//******************請注意這裡*******************
    }
}

編譯一下,ok通過,然後執行,輸出是:

D:\JAVA\java3>java ClassDemo1
null

為什麼呢?明明在主函式中傳了值“white”了啊,這裡為什麼是null呢?問題就出在了 color = color 這裡,這裡兩個變數名一樣,說簡單點,就是把電腦整懵逼了,那為了避免歧義,這時候就需要this關鍵詞了
把它改為 this.color = color 就可以了。因為this代表的是本類物件的引用,如此一來就不會產生歧義了,再次執行,結果就輸出了white。

類似的問題也出現在繼承中,子類想引用父類的建構函式怎麼辦?,ok,super就是來做這個的

super.xxx

  1. 訪問超類成員

super()

  1. 訪問超類建構函式
  2. 必須是第一行程式碼
  3. 建構函式的首行,要麼是this(),要麼是super(),預設是super()

super和this對比

super和this都可以看成是類中內建的成員變數,其中this是指向物件自身的引用,而super是指向超類物件中的一個引用。

注:必須寫第一行的是super(),它呼叫的是建構函式;而super.xxx,它是一個引用,是一個指向父類物件的一個引用,不用必須放在第一行。

函式的覆蓋

什麼是函式的覆蓋?就是overwrite,也叫重寫、複寫,概念是:子類中出現與父類一模一樣的方法時,會出現覆蓋操作,也稱為重寫或者複寫。
注意,父類中的private私有方法不可以被覆蓋。在子類覆蓋方法中,繼續使用被覆蓋的方法可以通過 super.函式名 來獲取。

覆蓋的注意事項:

  • 覆蓋時,子類方法許可權一定要大於等於父類方法許可權
  • 靜態覆蓋靜態,非靜態覆蓋非靜態,靜態性約束保持一致
  • 繼承的時候許可權可以放大,但是不可以縮小

    覆蓋的應用

    當子類需要父類的功能,而功能主體子類有自己特有內同時,可以複寫父類中的方法,這樣,既沿襲了父類的功能,有定義了子類特有的內容。

始終記住一句話:任何物件的建立都意味著整個家族樹的建立

子類例項化的過程

  • 子類中所有的建構函式預設都會訪問父類中空引數的建構函式,因為每一個建構函式的第一行都有一條預設的語句super();
  • 子類會具備父類中的資料,所以要先明確父類是如何對這些資料初始化的
  • 當父類中沒有空引數的建構函式時,子類的建構函式必須通過this或者super語句指定要訪問的建構函式。

final關鍵字

  • final 可以修飾類、方法、變數。如果修飾類,不能被繼承。(斷子絕孫)
  • final 修飾的方法不可以被覆蓋
  • final 如果修飾變數,同樣不能被修改,只是最初可以賦值一次,也叫常量(不能發生變化),但是可以被呼叫

內部類

  • 1.定義在類內部的類成為內部類
  • 2.內部類可以在類成員位置上,編譯時產生的類:外部類$內部類名,例如:Benz$Engine.class
  • 3.內部類還可以在方法內定義,編譯時產生的類:Benz$1Engine.class
  • 4.內部類訪問區域性變數時,不能區域性變數進行重新賦值,java8不要求必須給區域性變數使用final修飾

抽象類 abstract

抽象定義:抽象就是從多個事物中共性的,本質的內容抽取出來

抽象類:Java中可以定義沒有方法體的方法,該方法的具體實現由子類完成,該方法稱為抽象方法,包含抽象方法的類就是抽象類。

抽象方法的由來:多個物件都具備相同的功能,但是功能具體內容有所不同,那麼在抽取過程中,只抽取了功能定義,並未抽取功能主體,那麼只有功能宣告,沒有功能主體的方法稱為抽象方法。例如:貓和狗都有吼叫的方法,所以抽象出來的動物雖然有吼叫功能,但是並不明確吼叫的細節。

抽象類的特點

  • 抽象類和抽象方法必須用abstract關鍵字來修飾
  • 抽象方法只有方法宣告,沒有方法體,定義在抽象類中。格式:修飾符 abstract 返回值型別 函式名(引數列表);
  • 抽象類不可以被例項化,也就是不可以用new建立物件。因為抽象類是具體事物抽出來的,本身就不是具體的,沒有對應的例項,比如犬科是一個抽象的概念,真正存在的是狼和狗。而且抽象類即使建立了物件,呼叫抽象方法也沒有意義。

    注意:

  • 1.抽象方法:沒有函式體的方法就是抽象方法,必須用abstract修飾
    • 抽象方法必須在抽象類中
    • 抽象類就像是一個不全的圖紙,是不能例項化的
    • 格式:修飾符 abstract 返回值 函式名(引數列表...);
    • 抽象類有建構函式
  • 2.非法修飾組合
    final + abstract
    private + abstract
    private + final (沒有意義)