第6篇-JAVA面向對象Ⅱ

第6篇-JAVA面向對象Ⅱ

  • 每篇一句 :敢於向黑暗宣戰的人,心中必定充滿光明

  • 初學心得: 面向對象 春暖花開

  • (筆者:JEEP/711)[JAVA筆記 | 時間:2017-04-05| JAVA面向對象 Ⅱ]



1.JAVA面向對象三大特徵

1.封裝(Encapsulation); 2.繼承(Inheritance); 3.多態(Polymorphism)

2.面向對象 之 封裝

什麼是封裝? 
封裝就是隱藏實現細節,僅對外提供訪問接口 
封裝的類型有:屬性封裝、方法封裝、類封裝、組件封裝、模塊化封裝、系統級封裝….

封裝的兩個含義: 
1.把對象的狀態和行爲看成一個統一的整體,將二者存放在一個獨立的模塊中(類) 
2.”信息隱藏”,把不需要讓外界知道的信息隱藏起來,儘可能隱藏對象功能實現細節,字段

封裝機制在程序中的體現: 
把描述對象的狀態用字段表示,描述對象的行爲用方法表示,把字段和方法定義在一個類中,並保證外界不能任意更改其內部的字段值,也不允許任意調動其內部的功能方法 
封裝在程序中的一種體現:通常將類中的成員變量私有化(private),通過對外提供方法(set方法,get方法),可對該變量(xxx)進行訪問

屬性的封裝 
當某些屬性或方法被修飾爲私有的,那麼這些屬性或方法就不能被類的外面直接訪問 
(1).把屬性定義爲私有的(只能在本類中訪問) 
(2).爲屬性提供getter取值方法、setter設置方法

封裝的優點 
● 1. 良好的封裝能夠減少耦合 
● 2. 類內部的結構可以自由修改 
● 3. 可以對成員變量進行更精確的控制 
● 4.模塊化、信息隱藏、實現細節、代碼重用、插件化易於調試、具有安全性

實現JAVA封裝步驟 
1.修改屬性的可見性來限制對屬性的訪問(一般爲private修飾符)

1./**
2.*定義一個Person類
3.*隱藏信息
4.**/
5.public class Person {
6.    private String name; //定義私有的屬性
7.    private int age; //定義私有屬性
8.}
9.這段代碼中,將 name 和 age 屬性設置爲私有的,只能本類才能訪問,其他類都訪問不了,如此就對信息進行了隱藏

2.對每個值屬性提供對外的公共方法訪問,也就是創建一對賦取值方法,用於對私有屬性的訪問

1./**
2.*定義一個Person類,隱藏信息並提供訪問
3.**/
4.public class Person{
5.    private String name; //定義私有的屬性
6.    private int age; //定義私有的屬性
7.    //取得getAge方法
8.public int getAge(){
9.      return age;
10.    }
11.    //取得getName方法
12. public String getName(){
13.      return name;
14.    }
15.    //設置setAge方法
16.public void setAge(int age){
17.      this.age = age;
18.    }
19.    //設置setName方法
20.public void setName(String name){
21.      this.name = name;
22.    }
23.}


3.面向對象 之 繼承

什麼是繼承(extends)? 
子類自動共享父類數據和方法的機制,這是類之間的關係就是叫做繼承 
繼承概念:被繼承的類稱爲父類(超類),繼承父類的類稱爲子類(派生類) 
繼承是指一個對象直接使用另一個對象的屬性和方法,通過繼承可以實現代碼重用

super關鍵字可以通過super關鍵字來實現對父類成員的訪問,用來引用當前對象的父類 
使用super調用父類中的屬性,調用父類的方法,調用父類中的構造方法 
super 表示父類對象的默認引用 
super如果子類要調用父類被覆蓋的實例方法,可用super作爲調用者調用父類被覆蓋的實例方法 
使用super調用父類方法,使用super調用父類的構造方法

this 與super 區別

NO.區別thissuper
1.使用調用本類中的字段或方法從子類調用父類中的字段或方法
2.構造可以調用本類構造方法,且有一個構造方法要作爲出口從子類調用父類的構造方法,不管子類如何安排最終一定會去調用,默認調用的是父類中的無參構造方法
3.要求調用自身構造方法時放在構造方法首行調用父類構造方法時放在子類構造方法首行
4.特殊表示當前對象表示父類對象

方法的覆寫:方法覆寫又稱爲方法覆蓋 
產生原因:當父類中某個方法不適合於子類時,子類出現父類一模一樣的方法 
調用被覆蓋的父類方法:使用super.方法名(實參); 
方法覆寫時應遵循的原則(一同,兩小,一大): 
(一同):方法簽名必須相同; 
(兩小):子類方法的返回值類型比父類方法的返回值類型更小或相等 
子類方法聲明拋出的異常應比父類方法申明拋出的異常更小或相等 
(一大):子類方法的訪問權限應比父類方法更大或相等

(Overload 重載) 與 (Override 覆寫) 區別

NO.區別(Overload)重載(Override)覆寫
1.判斷規則兩同一不同一同兩小一大
2.權限沒有權限要求被覆寫的方法不能擁有比父類更嚴格的權限
3.範圍發生在一個類中發生在繼承關係中
4.術語OverloadOverride
5.多態編譯時多態運行時多態

子類對象實例化過程 
在繼承操作中,對於子類對象的實例化: 
子類對象在實例化之前必須首先調用父類中的構造方法之後再調用自身的構造方法 
在子類進行實例化操作時,首先會讓其父類進行實例化操作(調用父類的構造方法),之後子類再自己進行實例化操作

子類訪問父類; 
子類不能直接訪問父類的私有成員,但是子類可以調用父類中的非私有方法來間接訪問父類的私有成員

在 JAVA中,類的繼承是單一繼承,也就是說,一個子類只能擁有一個父類,所以 extends 只能繼承一個類 
類的繼承格式:在 JAVA中通過 extends 關鍵字可以申明一個類是從另外一個類繼承而來的

1./**
2.*定義一個類
3.**/
4.class 父類 {
5.}
6./**
7.*定義一個類繼承父類
8.**/
9.class 子類 extends 父類 {
10.}

爲什麼需要繼承? :接下來筆者通過代碼實例來說明這個需求 
開發汽車類,其中汽車分別爲奧迪A6以及奔馳R350,要求如下: 
● 奧迪A6:屬性(id,車名,顏色,速度),方法(汽車基本信息,汽車動力信息) 
● 奔馳R350:屬性(id,車名,顏色,速度),方法(汽車基本信息,汽車動力信息)

1.奧迪A6 汽車類
2.public class AudiA6 { 
3.    private int id; //定義私有汽車id號屬性
4.    private String carname; //定義私有車名屬性
5.    private String colors; //定義私有顏色屬性
6.    private double speed; //定義私有速度屬性
7.      //定義帶參構方法
8. public AudiA6(int id,String carname,String colors,double speed){ 
9.            this.id = id; 
10.            this.carname = carname; 
11.            this.colors = colors;
12.            this.speed = speed;
13.    } 
14.   //取得getId方法
15. public int getId(){
16.      return id;
17.    }
18.    //取得getCarname方法
19. public String getCarname(){
20.      return carname;
21.    }
22.    //取得getColors方法
23. public String getColors(){
24.      return colors;
25.    }
26.    //取得getSpeed方法
27. public String getSpeed(){
28.      return speed;
29.    }
30. //設置setId方法
31. public void setId(int Id){
32.      this.id = id;
33.    }
34.    //設置setCarname方法
35. public void setCarname(String carname){
36.      this.carname = carname;
37.    }
38.    //設置setColors方法
39. public void setColors(String colors){
40.      this.colors = colors;
41.    }
42.      //設置setSpeed方法
43. public void setSpeed(double speed){
44.      this.speed = speed;
45.    }
46.   //定義汽車基本信息方法
47.  public void carinformation(){ 
48.          System.out.println("汽車基本信息:" +id+carname+colors); //輸出汽車id,車名,顏色
49.    }
50.    //定義汽車動力信息方法
51.  public void information(){
52.          System.out.println("汽車動力信息"+ speed); //輸出速度
53.    }
54.}
55.
56.
57.奔馳R350 汽車類
58.public class MercedesBenzR350 { 
59.    private int id; //定義私有汽車id號屬性
60.    private String carname; //定義私有車名屬性
61.    private String colors; //定義私有顏色屬性
62.    private double speed; //定義私有速度屬性
63.      //定義帶參構方法
64. public MercedesBenzR350 (int id,String carname,String colors,double speed){ 
65.            this.id = id; 
66.            this.carname = carname; 
67.            this.colors = colors;
68.            this.speed = speed;
69.    } 
70.   //取得getId方法
71. public int getId(){
72.      return id;
73.    }
74.    //取得getCarname方法
75. public String getCarname(){
76.      return carname;
77.    }
78.    //取得getColors方法
79. public String getColors(){
80.      return colors;
81.    }
82.    //取得getSpeed方法
83. public String getSpeed(){
84.      return speed;
85.    }
86. //設置setId方法
87. public void setId(int Id){
88.      this.id = id;
89.    }
90.    //設置setCarname方法
91. public void setCarname(String carname){
92.      this.carname = carname;
93.    }
94.    //設置setColors方法
95. public void setColors(String colors){
96.      this.colors = colors;
97.    }
98.      //設置setSpeed方法
99. public void setSpeed(double speed){
100.      this.speed = speed;
101.    }
102.   //定義汽車基本信息方法
103.  public void carinformation(){ 
104.          System.out.println("汽車基本信息:" +id+carname+colors); //輸出汽車id,車名,顏色
105.    }
106.    //定義汽車動力信息方法
107.  public void information(){
108.          System.out.println("汽車動力信息"+ speed); //輸出速度
109.    }
110.}

從這兩段代碼我們可以看出來,存在太多重複代碼,導致後果就是代碼量大且非常多,而且維護性不高(維護性主要是後期需要修改的時候,就需要修改很多的代碼,容易出錯)

所以要從根本上解決這兩段代碼的問題,我們就需要繼承,將兩段代碼中相同的部分提取出來組成 一個父類

1.公共的汽車父類:
2.public class Cars { 
3.   private int id; //定義私有汽車id號屬性
4.    private String carname; //定義私有車名屬性
5.    private String colors; //定義私有顏色屬性
6.    private double speed; //定義私有速度屬性
7.      //定義帶參構方法
8. public Cars (int id,String carname,String colors,double speed){ 
9.            this.id = id; 
10.            this.carname = carname; 
11.            this.colors = colors;
12.            this.speed = speed;
13.    } 
14.   //取得getId方法
15. public int getId(){
16.      return id;
17.    }
18.    //取得getCarname方法
19. public String getCarname(){
20.      return carname;
21.    }
22.    //取得getColors方法
23. public String getColors(){
24.      return colors;
25.    }
26.    //取得getSpeed方法
27. public String getSpeed(){
28.      return speed;
29.    }
30. //設置setId方法
31. public void setId(int Id){
32.      this.id = id;
33.    }
34.    //設置setCarname方法
35. public void setCarname(String carname){
36.      this.carname = carname;
37.    }
38.    //設置setColors方法
39. public void setColors(String colors){
40.      this.colors = colors;
41.    }
42.      //設置setSpeed方法
43. public void setSpeed(double speed){
44.      this.speed = speed;
45.    }
46.   //定義汽車基本信息方法
47.  public void carinformation(){ 
48.          System.out.println("汽車基本信息:" +id+carname+colors); //輸出汽車id,車名,顏色
49.    }
50.    //定義汽車動力信息方法
51.  public void information(){
52.          System.out.println("汽車動力信息"+ speed); //輸出速度
53.    }
54.}

這個Cars類就可以作爲一個父類,然後奧迪A6汽車類和奔馳R350汽車類繼承Cars公共汽車類之後,就具有父類當中的屬性和方法,

子類就不會存在重複的代碼,維護性也提高,代碼也更加簡潔,提高代碼的複用性(複用性主要是可以多次使用,不用再多次寫同樣的代碼)


繼承之後的代碼

1.奧迪A6汽車類         繼承Cars公共類:
2.public class AudiA6 extends Cars { 
3.        //帶參構造方法
4.    public AudiA6(int id,String carname,String colors,double speed) { 
5.        super(id, carname, colors, speed);  
6.    } 
7.     //定義汽車基本信息方法
8.  public void carinformation(){ 
9.         super.carinformation(); //super調用父類的方法
10.    }
11.    //定義汽車動力信息方法
12.  public void information(){
13.          super.carinformation(); //super調用父類的方法
14.    }
15.}
16.
17.
18.奔馳R350汽車類                 繼承Cars公共類:
19.public class MercedesBenzR350 extends Cars { 
20.    public MercedesBenzR350(int id,String carname,String colors,double speed) { 
21.        super(id, carname, colors, speed); 
22.    } 
23.     //定義汽車基本信息方法
24.  public void carinformation(){ 
25.         super.carinformation(); //super調用父類的方法
26.    }
27.    //定義汽車動力信息方法
28.  public void information(){
29.          super.carinformation(); //super調用父類的方法
30.    }
31.}

繼承的特性 
● 子類擁有父類非private的屬性,方法 
● 子類可以擁有自己的屬性和方法,即子類可以對父類進行擴展 
● 子類可以用自己的方式實現父類的方法 
● Java的繼承是單繼承,但是可以多重繼承,單繼承就是一個子類只能繼承一個父類 
多重繼承就是,例如A類繼承B類,B類繼承C類,所以按照關係就是C類是B類的父類,B類是A類的父類 
這是java繼承區別於C++繼承的一個特性 
● 提高了類之間的耦合性(繼承的缺點,耦合度高就會造成代碼之間的聯繫)

4.面向對象 之 多態

什麼是多態?: 多態性指同一個實體同時具有多種形式 
多態是同一個行爲具有多個不同表現形式或形態的能力,多態性是對象多種表現形式的體現 
譯時的類型由聲明該變量時使用的類型決定 
運行時的類型由實際賦給變量的對象決定,如果編譯時類型和運行時類型不同,就出現多態性

生活中多態的例子: 
比如我們說”寵物”這個對象,它就有很多不同的表達或實現,比如有小貓、小狗、等等 
那麼我到寵物店說”請給我一隻寵物”,服務員給我小貓、小狗或者蜥蜴都可以,我們就說”寵物”這個對象就具備多態性

多態的實現方式: 
1.方法的重載(同一個類裏面,返回值相同,方法名相同,參數的個數不同),重寫(發生在子類與父類關係中) 
2.對象的多態性:是從繼承關係中的多個類而來,引用變量類型轉換 
向上轉型:將子類實例化轉爲父類實例格式: 
向上轉型(子類→父類):(自動完成) 父類名稱 父類對象 = 子類實例 ; 
向下轉型(父類→子類):(強制完成) 子類名稱 子類對象 = (子類名稱)父類實例 ; 
3.接口 
● 生活中的接口最具代表性的就是插座,例如一個三接頭的插頭都能接在三孔插座中,因爲這個是每個國家都有各自規定的接口規則,有可能到國外就不行,那是因爲國外自己定義的接口類型 
● JAVA中的接口類似於生活中的接口,就是一些方法特徵的集合,但沒有方法的實現 
4.抽象類和抽象方法

多態的作用:把不同的子類對象都當作父類來看,可以屏蔽不同子類對象之間的差異,寫出通用的代碼,做出通用的編程,以適應需求的不斷變化,只修改方法的實現,不必修改方法的聲明,繼承是多態產生的前提條件

多態的分類:編譯時多態:方法重載,運行時多態:方法覆寫

多態的優點 
● 1. 消除類型之間的耦合關係 
● 2. 可替換性 
● 3. 可擴充性 
● 4. 接口性 
● 5. 靈活性 
● 6. 簡化性


初學(面向對象三大特徵) Ⅱ 難點: ★★★★★★

希望每一篇文章都能夠對讀者們提供幫助與提升,這乃是每一位筆者的初衷


感謝您的閱讀 歡迎您的留言與建議

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章