封裝、繼承和多態

封裝

封裝(Encapsulation)是面向對象的三大特徵之一(另外兩個是繼承和多態),它指的是將對象的狀態信息隱藏在對象內部,不容許外部程序直接訪問對象內部信息,而是經過該類所提供的方法來實現對內部信息的操做和訪問。java

訪問控制符

Java 提供了 3 個訪問控制符:private、 protected 和 public ,表明 3 種不一樣的訪問級別,再加上一個默認的訪問控制級別(不使用任何訪問控制符),共有 4 個訪問控制級別。ide

  • private(當前類訪問權限):類中的一個的成員被 private 修飾,它只能在當前類的內部被訪問;函數

  • default(包訪問權限):類中的一個成員或者一個外部類不使用任何訪問控制符修飾,它能被當前包下其餘類訪問;this

  • protected(子類訪問權限):類中的一個的成員被 protected 修飾,它既能夠被當前包下的其餘類訪問,又能夠被不一樣包的子類訪問;code

  • public(公共訪問權限):類中的一個成員或者一個外部類使用 public 修飾,它能被全部類訪問。對象

private default protected public
同一個類中
同一個包中
子類中
全局範圍內


繼承

  • Java 使用 extends 做爲繼承的關鍵字,子類擴展了父類,得到父類的所有成員變量和方法。
  • Java 只能單繼承,只有一個直接父類,但能夠有無限多個間接父類。當一個 Java 類並未顯式指定直接父類時,默認繼承 java.lang.Object ,所以 java.lang.Object 是全部類的直接或間接父類。

重寫父類方法

重寫父類方法應遵循 「兩同兩小一大「 規則:blog

  • 「兩同」 指方法名相同、形參列表相同;
  • 「兩小」 指子類方法返回值類型和拋出的異常類型應比父類方法的更小或相等;
  • 「一大」 指的是子類方法的訪問權限應比父類方法的訪問權限更大或相等。
class B {
    public void show() {
        System.out.println("B");
    }
}

public class A extends B{
    @Override
    public void show() {
        System.out.println("A");  //重寫父類方法
    }
}

重載(Overload)和重寫(Override)區別:繼承

  • 重載指的是同一類中多個同名方法;
  • 重寫指的是子類和父類的同名方法。

super關鍵字

  • 訪問父類的構造函數:可使用 super() 函數訪問父類的構造函數,從而委託父類完成一些初始化的工做;
  • 訪問父類的成員:若是子類重寫了父類的某個方法,能夠經過使用 super 關鍵字來引用父類的方法實現。
class B {
    private int x;

    public B(int x) {
        this.x = x;
    }

    public void show() {
        System.out.println("x:" + x);
    }
}

public class A extends B{
    private int x;

    public A(int x, int x1) {
        super(x1);
        this.x = x;
    }

    @Override
    public void show() {
        super.show();  //調用被覆蓋的父類方法
    }

    public static void main(String[] args) {
        A a = new A(1, 2);
        a.show();  //x:2
    }
}

父類構造器

子類繼承了父類的所有變量和方法,因此實例化子類時,必須先將其父類實例化。調用父類構造器的方式是 super(),參數爲父類構造器所需參數。使用 super 調用父類構造器必須出現放在子類構造器的第一行,而 this 調用同一個類中重載的構造器也要放在第一行,因此 super() 和 this() 不能同時出現。get

無論是否使用 super 顯式調用父類構造器,子類構造器總會調用父類構造器一次,總共會出現三種狀況:io

  • 子類構造器第一行使用 super 顯式調用父類構造器;
  • 子類構造器第一行使用 this 調用重載的子類構造器,在本類重載的構造器中調用父類構造器;
  • 子類構造器第一行既沒有 super 調用,也沒有 this 調用,系統在第一行隱私調用父類無參構造器。


多態

多態:相同類型的變量調用同一個方法時呈現出多種不一樣的行爲特徵。

產生緣由:Java 容許把一個子類對象直接賦給一個父類引用變量,無須任何類型轉換。當把一個子類對象賦給父類引用變量時,會出現編譯類型和運行類型不一致的狀況,此時調用子類和父類的同名方法時(這裏的同名指的是子類重寫了父類方法),老是表現出子類方法的行爲特徵。例如:B b = new A() 編譯類型看左邊,運行類型看右邊,所以編譯類型爲 B,運行類型爲 A,當 b 調用 A 和 B 的同名的方法時,運行的老是 A 中的方法。

class B {
    public String book = "B";

    public void base() {
        System.out.println("父類普通方法");
    }

    public void test() {
        System.out.println("父類被覆蓋的方法");
    }

    public String getBook() {
        return book;
    }
}

public class A extends B{
    public String book = "A";
    @Override
    public void test() {
        System.out.println("子類覆蓋父類方法");
    }
    public void sub() {
        System.out.println("子類普通方法");
    }
    @Override
    public String getBook() {
        return book;
    }

    public static void main(String[] args) {
        B b = new B();
        System.out.println(b.book);  //B
        b.base();                    //父類普通方法
        b.test();                    //父類被覆蓋的方法
        System.out.println(b.getBook()); //B

        A a = new A();
        System.out.println(a.book);  //A
        a.base();                    //父類普通方法
        a.test();                    //子類覆蓋父類方法
        System.out.println(a.getBook());  //A

        //編譯看左邊,運行看右邊,編譯和運行不一致
        B b1 = new A();
        //訪問的是父類的屬性,與方法不一樣,實例變量不具備多態性
        System.out.println(b1.book);  //B
        //訪問父類繼承的方法
        b1.base();                   //父類普通方法
        //訪問的是子類的同名方法
        b1.test();                    //子類覆蓋父類方法
        //B沒有提供sub()方法,就算A有,也沒法經過編譯
        //b1.sub();                   //錯誤
        System.out.println(a.getBook()); //A
    }
}

當代碼運行 B b1 = new A() 時,編譯類型爲 B,運行類型爲 A。

當調用 b1.test() 方法時(B 中有 test() 方法,A 中將其覆蓋了),實際運行的是 A 的 test() 方法,方法行爲老是表現出子類方法的行爲特徵,而不是父類方法的行爲特徵,這就是多態。

當執行 b1.base() 方法時,由於子類繼承了父類的該方法,而且沒有重寫,因此運行一致。

當執行 b1.sub() 方法時,因爲父類沒有 sub() 方法,而編譯時類型爲父類,因此沒法經過編譯。

當執行 b1.book 獲取同名實例變量時,返回的是父類的實例變量,與方法不一樣,對象的實例變量則不具有多態性,返回的數據看編譯時的類型。

當執行 b1.getBook() 方法時,實際運行的是 A 的 getBook() 方法 ,內部訪問的實例變量是 A 的,方法是表現出多態特性。

注意:只有調用子類重寫父類的方法才表現出多態性,直接訪問公開的同名實例變量時不表現多態性,返回的數據看左邊類型(編譯類型)。

相關文章
相關標籤/搜索