1. 程式人生 > 其它 >【小白轉碼】06

【小白轉碼】06

第六章

一、封裝 encapsulation

1.遵循的原則

隨著我們系統越來越複雜,類會越來越多,那麼類之間的訪問邊界必須把握好,面向物件的開發原則要遵循“高內聚、低耦合”,而“高內聚,低耦合”的體現之一:

  • 高內聚:類的內部資料操作細節自己完成,不允許外部干涉;

  • 低耦合:僅對外暴露少量的方法用於使用

通俗的講,封裝就是把該隱藏的隱藏起來,該暴露的暴露出來。

 

2.許可權修飾符

許可權修飾符共有4種,分別為public,protected、預設、private;許可權修飾符可以使得資料在一定範圍內可見或者隱藏。

修飾符 本類 本包 其他包子類 任意位置
private
× × ×
預設 × ×
protected ×
public

許可權修飾符可以修飾:

外部類:public和預設

成員變數、成員方法、構造器、成員內部類:public,protected,預設,private

 

3.類的封裝

  1. 類的封裝的意義:

    • 隱藏類的實現細節

   - 讓使用者只能通過事先預定的方法來訪問資料,從而可以在該方法裡面加入控制邏輯,限制對成員變數的不合理訪問。還可以進行資料檢查,從而有利於保證物件資訊的完整性。
   - 便於修改,提高程式碼的可維護性。主要說的是隱藏的部分,在內部修改了,如果其對外可以的訪問方式不變的話,外部根本感覺不到它的修改。例如:Java8->Java9,String從char[]轉為byte[]內部實現,而對外的方法不變,我們使用者根本感覺不到它內部的修改。
  1. 如何進行類的封裝?

    • 成員變數(field)私有化

    • 提供標準的get/set方法

 

二、基礎 inherit

1.Java中的繼承

Java中有父類、子類的概念,類似生活中的父子關係,父類中的一些屬性和方法可以被子類繼承下來使用,不再需要重複定義。

 

2.繼承的特點

2.1 子類會繼承父類所有的成員變數和方法

2.2 子類無法直接使用父類的私有成員

2.3 Java只支援單繼承

2.4 Java支援多層繼承

2.5 一個類可以同時擁有多個子類

 

3.方法的重寫 override

當子類繼承了父類的某個方法之後,發現這個方法並不能滿足子類的實際需求,那麼可以通過方法重寫,覆蓋父類的方法。

3.1 方法重寫:

子類中定義與父類中相同的方法,一般方法體不同,用於改造並覆蓋父類的方法。

3.2 方法重寫的具體要求:

  1. 必須保證父子類之間重寫方法的名稱相同。

  2. 必須保證父子類之間重寫方法的引數列表也完全相同。

  3. 子類方法的返回值型別必須【小於等於】父類方法的返回值型別(小於其實就是是它的子類,例如:Cat< Animal)。

    注意:如果返回值型別是基本資料型別和void,那麼必須是相同

  4. 子類方法的許可權必須【大於等於】父類方法的許可權修飾符。

    注意:public > protected > 預設 > private

    父類私有方法不能重寫

    跨包的父類預設的方法也不能重寫

另外:

靜態方法不能被重寫,方法重寫指的是例項方法重寫,靜態方法屬於類的方法不能被重寫,而是隱藏。

final修飾的方法不能被重寫

父類private方法不能重寫

三、多型polymorphism

1.多型的形式

Java規定父類型別的變數可以接收子類型別的物件,這一點從邏輯上也是說得通的。

父類型別 變數名 = 子類物件;

父類型別:指子類繼承的父類型別,或者實現的父介面型別。

所以說繼承是多型的前提

//多型的引用形式
Animal a = new Cat();//Cat物件也屬於其父類Animal型別。貓也是一個動物。

 

2.多型的表現

多型引用形式的具體表現:編譯時型別與執行時型別不一致,編譯時看左邊的“父類”,執行時看右邊的“子類”。

也就是我們常說的:編譯看左邊,執行看右邊。

3.多型的好處

執行時,看“子類”,如果子類重寫了方法,一定是執行子類重寫的方法;變數引用的子類物件不同,執行的方法就不同,實現動態繫結。程式碼編寫更靈活、功能更強大,可維護性和擴充套件性更好了。

  1. 提高程式的擴充套件性(參考引入案例分析)

  2. 降低類與類之間的耦合度(參考引入案例分析)

 

4.向上轉型與向下轉型

首先,一個物件在new的時候建立是哪個型別的物件,它從頭至尾都不會變。即這個物件的執行時型別,本質的型別用於不會變。但是,把這個物件賦值給不同型別的變數時,這些變數的編譯時型別卻不同。

這個和基本資料型別的轉換是不同的。基本資料型別是把資料值copy了一份,相當於有兩種資料型別的值。而物件的賦值不會產生兩個物件。

1、為什麼要型別轉換呢?

因為多型,就一定會有把子類物件賦值給父類變數的時候,這個時候,在編譯期間,就會出現型別轉換的現象。

但是,使用父類變數接收了子類物件之後,我們就不能呼叫子類擁有,而父類沒有的方法了。這也是多型給我們帶來的一點"小麻煩"。所以,想要呼叫子類特有的方法,必須做型別轉換,使得編譯通過

  • 向上轉型:當左邊的變數的型別(父類) > 右邊物件/變數的型別(子類),我們就稱為向上轉型

    • 此時,編譯時按照左邊變數的型別處理,就只能呼叫父類中有的變數和方法,不能呼叫子類特有的變數和方法了

    • 但是,執行時,仍然是物件本身的型別,所以執行的方法是子類重寫的方法體。

    • 此時,一定是安全的,而且也是自動完成的

  • 向下轉型:當左邊的變數的型別(子類)<右邊物件/變數的編譯時型別(父類),我們就稱為向下轉型

    • 此時,編譯時按照左邊變數的型別處理,就可以呼叫子類特有的變數和方法了

    • 但是,執行時,仍然是物件本身的型別

    • 不是所有通過編譯的向下轉型都是正確的,可能會發生ClassCastException,為了安全,可以通過isInstanceof關鍵字進行判斷

 

5.如何向上轉型與向下轉型

向上轉型:自動完成

向下轉型:(子類型別)父類變數

 

6.instanceof關鍵字

instanceof關鍵字用於判斷一個物件的執行時型別

為了避免ClassCastException的發生,Java提供了 instanceof 關鍵字,給引用變數做型別的校驗,只要用instanceof判斷返回true的,那麼強轉為該型別就一定是安全的,不會報ClassCastException異常。

格式:

變數/匿名物件 instanceof 資料型別 

那麼,哪些instanceof判斷會返回true呢?

  • 變數/匿名物件的編譯時型別 與 instanceof後面資料型別是直系親屬關係才可以比較

  • 變數/匿名物件的執行時型別<= instanceof後面資料型別,才為true

     

第六章

一、封裝 encapsulation

1.遵循的原則

隨著我們系統越來越複雜,類會越來越多,那麼類之間的訪問邊界必須把握好,面向物件的開發原則要遵循“高內聚、低耦合”,而“高內聚,低耦合”的體現之一:

  • 高內聚:類的內部資料操作細節自己完成,不允許外部干涉;

  • 低耦合:僅對外暴露少量的方法用於使用

通俗的講,封裝就是把該隱藏的隱藏起來,該暴露的暴露出來。

 

2.許可權修飾符

許可權修飾符共有4種,分別為public,protected、預設、private;許可權修飾符可以使得資料在一定範圍內可見或者隱藏。

修飾符 本類 本包 其他包子類 任意位置
private × × ×
預設 × ×
protected ×
public

許可權修飾符可以修飾:

外部類:public和預設

成員變數、成員方法、構造器、成員內部類:public,protected,預設,private

 

3.類的封裝

  1. 類的封裝的意義:

    • 隱藏類的實現細節

   - 讓使用者只能通過事先預定的方法來訪問資料,從而可以在該方法裡面加入控制邏輯,限制對成員變數的不合理訪問。還可以進行資料檢查,從而有利於保證物件資訊的完整性。
   - 便於修改,提高程式碼的可維護性。主要說的是隱藏的部分,在內部修改了,如果其對外可以的訪問方式不變的話,外部根本感覺不到它的修改。例如:Java8->Java9,String從char[]轉為byte[]內部實現,而對外的方法不變,我們使用者根本感覺不到它內部的修改。
  1. 如何進行類的封裝?

    • 成員變數(field)私有化

    • 提供標準的get/set方法

 

二、基礎 inherit

1.Java中的繼承

Java中有父類、子類的概念,類似生活中的父子關係,父類中的一些屬性和方法可以被子類繼承下來使用,不再需要重複定義。

 

2.繼承的特點

2.1 子類會繼承父類所有的成員變數和方法

2.2 子類無法直接使用父類的私有成員

2.3 Java只支援單繼承

2.4 Java支援多層繼承

2.5 一個類可以同時擁有多個子類

 

3.方法的重寫 override

當子類繼承了父類的某個方法之後,發現這個方法並不能滿足子類的實際需求,那麼可以通過方法重寫,覆蓋父類的方法。

3.1 方法重寫:

子類中定義與父類中相同的方法,一般方法體不同,用於改造並覆蓋父類的方法。

3.2 方法重寫的具體要求:

  1. 必須保證父子類之間重寫方法的名稱相同。

  2. 必須保證父子類之間重寫方法的引數列表也完全相同。

  3. 子類方法的返回值型別必須【小於等於】父類方法的返回值型別(小於其實就是是它的子類,例如:Cat< Animal)。

    注意:如果返回值型別是基本資料型別和void,那麼必須是相同

  4. 子類方法的許可權必須【大於等於】父類方法的許可權修飾符。

    注意:public > protected > 預設 > private

    父類私有方法不能重寫

    跨包的父類預設的方法也不能重寫

另外:

靜態方法不能被重寫,方法重寫指的是例項方法重寫,靜態方法屬於類的方法不能被重寫,而是隱藏。

final修飾的方法不能被重寫

父類private方法不能重寫

三、多型polymorphism

1.多型的形式

Java規定父類型別的變數可以接收子類型別的物件,這一點從邏輯上也是說得通的。

父類型別 變數名 = 子類物件;

父類型別:指子類繼承的父類型別,或者實現的父介面型別。

所以說繼承是多型的前提

//多型的引用形式
Animal a = new Cat();//Cat物件也屬於其父類Animal型別。貓也是一個動物。

 

2.多型的表現

多型引用形式的具體表現:編譯時型別與執行時型別不一致,編譯時看左邊的“父類”,執行時看右邊的“子類”。

也就是我們常說的:編譯看左邊,執行看右邊。

3.多型的好處

執行時,看“子類”,如果子類重寫了方法,一定是執行子類重寫的方法;變數引用的子類物件不同,執行的方法就不同,實現動態繫結。程式碼編寫更靈活、功能更強大,可維護性和擴充套件性更好了。

  1. 提高程式的擴充套件性(參考引入案例分析)

  2. 降低類與類之間的耦合度(參考引入案例分析)

 

4.向上轉型與向下轉型

首先,一個物件在new的時候建立是哪個型別的物件,它從頭至尾都不會變。即這個物件的執行時型別,本質的型別用於不會變。但是,把這個物件賦值給不同型別的變數時,這些變數的編譯時型別卻不同。

這個和基本資料型別的轉換是不同的。基本資料型別是把資料值copy了一份,相當於有兩種資料型別的值。而物件的賦值不會產生兩個物件。

1、為什麼要型別轉換呢?

因為多型,就一定會有把子類物件賦值給父類變數的時候,這個時候,在編譯期間,就會出現型別轉換的現象。

但是,使用父類變數接收了子類物件之後,我們就不能呼叫子類擁有,而父類沒有的方法了。這也是多型給我們帶來的一點"小麻煩"。所以,想要呼叫子類特有的方法,必須做型別轉換,使得編譯通過

  • 向上轉型:當左邊的變數的型別(父類) > 右邊物件/變數的型別(子類),我們就稱為向上轉型

    • 此時,編譯時按照左邊變數的型別處理,就只能呼叫父類中有的變數和方法,不能呼叫子類特有的變數和方法了

    • 但是,執行時,仍然是物件本身的型別,所以執行的方法是子類重寫的方法體。

    • 此時,一定是安全的,而且也是自動完成的

  • 向下轉型:當左邊的變數的型別(子類)<右邊物件/變數的編譯時型別(父類),我們就稱為向下轉型

    • 此時,編譯時按照左邊變數的型別處理,就可以呼叫子類特有的變數和方法了

    • 但是,執行時,仍然是物件本身的型別

    • 不是所有通過編譯的向下轉型都是正確的,可能會發生ClassCastException,為了安全,可以通過isInstanceof關鍵字進行判斷

 

5.如何向上轉型與向下轉型

向上轉型:自動完成

向下轉型:(子類型別)父類變數

 

6.instanceof關鍵字

instanceof關鍵字用於判斷一個物件的執行時型別

為了避免ClassCastException的發生,Java提供了 instanceof 關鍵字,給引用變數做型別的校驗,只要用instanceof判斷返回true的,那麼強轉為該型別就一定是安全的,不會報ClassCastException異常。

格式:

變數/匿名物件 instanceof 資料型別 

那麼,哪些instanceof判斷會返回true呢?

  • 變數/匿名物件的編譯時型別 與 instanceof後面資料型別是直系親屬關係才可以比較

  • 變數/匿名物件的執行時型別<= instanceof後面資料型別,才為true