深度講解OOP——面向對象編程

桃李云帮 2024-04-10 16:24 15次浏览 0 条评论 taohigo.com

第一節 類和對象

1.1面向過程和面向對象

面向過程和面向對象都是對軟件分析、設計和開發的一種思想,它指導著人們以不同的方式去分析、設計和開發軟件。

早期先有面向過程思想,隨著軟件規模的擴大,問題復雜性的提高,面向過程的弊端越來越明顯的顯示出來,出現瞭面向對象思想並成為目前主流的方式。兩者都貫穿於軟件分析、設計和開發各個階段,對應面向對象就分別稱為面向對象分析(OOA)、面向對象設計(OOD)和面向對象編程(OOP)。C語言是一種典型的面向過程語言,Java是一種典型的面向對象語言。

示例1:開車和造車

面向過程思想思考問題時,我們首先思考“怎麼按步驟實現?”並將步驟對應成方法,一步一步,最終完成。 這個適合簡單任務,不需要過多協作的情況下。比如,如何開車?我們很容易就列出實現步驟:

面向過程適合簡單、不需要協作的事務,重點關註如何執行。

但是當我們思考比較復雜的設計任務時,比如“如何造車?”,就會發現列出1234這樣的步驟,是不可能的。那是因為,造車太復雜,需要很多協作才能完成。此時面向對象思想就應運而生瞭。

面向對象(Oriented-Object)思想更契合人的思維模式。我們首先思考的是“怎麼設計這個事物?” 比如思考造車,我們就會先思考“車怎麼設計?”,而不是“怎麼按步驟造車的問題”。這就是思維方式的轉變。

比如,我們用面向對象思想思考“如何設計車”:

天然的,我們就會從“車由什麼組成”開始思考。發現,車由如下對象組成:

為瞭便於協作,我們找輪胎廠完成制造輪胎的步驟,發動機廠完成制造發動機的步驟;這樣,發現大傢可以同時進行車的制造,最終進行組裝,大大提高瞭效率。但是,具體到輪胎廠的一個流水線操作,仍然是有步驟的,還是離不開執行者、離不開面向過程思維!

因此,面向對象可以幫助我們從宏觀上把握、從整體上分析整個系統。 但是,具體到實現部分的微觀操作(就是一個個方法),仍然需要面向過程的思路去處理。

我們千萬不要把面向過程和面向對象對立起來。他們是相輔相成的。面向對象離不開面向過程!

示例2:蛋炒飯和蓋澆飯

簡單來說:用面向過程的方法寫出來的程序是一份蛋炒飯,而用面向對象寫出來的程序是一份蓋澆飯。所謂蓋澆飯,就是在米飯上面澆上一份蓋菜,你喜歡什麼菜,你就澆上什麼菜。我覺得這個比喻還是比較貼切的。

蛋炒飯肯定是把米飯和雞蛋混在一起炒勻。蓋澆飯呢,則是把米飯和蓋菜分別做好,你如果要一份紅燒肉蓋飯呢,就給你澆一份紅燒肉;如果要一份青椒土豆蓋澆飯,就給澆一份青椒土豆絲。

蛋炒飯的好處是入味均勻,吃起來香。如果恰巧你不愛吃雞蛋,隻愛吃青菜的話,那麼唯一的辦法就是全部倒掉,重新做一份青菜炒飯瞭。蓋澆飯就沒這麼多麻煩,你隻需要把上面的蓋菜撥掉,更換一份蓋菜就可以瞭。蓋澆飯的缺點是入味不均,可能沒有蛋炒飯那麼香。

到底是蛋炒飯好還是蓋澆飯好呢?其實這類問題都很難回答,非要比個上下高低的話,就必須設定一個場景,否則隻能說是各有所長。那麼從飯館角度來講的話,做蓋澆飯顯然比蛋炒飯更有優勢,他可以組合出來任意多的組合,而且不會浪費。

蓋澆飯的好處就是“菜”“飯”分離,從而提高瞭制作蓋澆飯的靈活性。飯不滿意就換飯,菜不滿意換菜。用軟件工程的專業術語就是“可維護性”比較好,“飯” 和“菜”的耦合度比較低。蛋炒飯將“蛋”“飯”攪和在一起,想換“蛋”“飯”中任何一種都很困難,耦合度很高,以至於“可維護性”比較差。軟件工程追求的目標之一就是可維護性。面向對象的好處之一就是顯著的改善瞭軟件系統的可維護性。

示例3:如何統一中國(一項極其復雜的系統工程)

面向對象和面向過程思想的總結

  • 都是解決問題的思維方式,都是代碼組織的方式。
  • 面向過程是一種“執行者思維”,解決簡單問題可以使用面向過程。
  • 面向對象是一種“設計者思維”,解決復雜、需要協作的問題可以使用面向對象。
  • 面向對象離不開面向過程:

宏觀上:通過面向對象進行整體設計

微觀上:執行和處理數據,仍然是面向過程。。

1.2理解類和對象

我們人認識世界,其實就是面向對象的(此對象可不是男女談對象的彼對象呀) 。比如現在讓大傢認識一下“天使”這個新事物,天使大傢沒見過吧,怎麼樣認識呢?最好的辦法就是,給你們面前擺4個天使,帶翅膀的美女,讓大傢看,看完以後,即使我不說,大傢下一次是不是就都認識天使瞭。

但是,看完10個天使後,我們總要總結一下,什麼樣的東東才算天使?天使是無數的,總有沒見過的!所以必須總結抽象,便於認識未知事物!總結的過程就是抽象的過程。小時候,我們學自然數時怎麼定義的?像1,2,3,4…這樣的數就叫做自然數。 通過抽象,我們發現天使有這樣一下特征:

1. 帶翅膀(帶翅膀不一定是天使,還可能是鳥人)

2. 女孩(天使掉下來臉著地,也是天使!)

3. 善良

4. 頭上有光環

那麼通過這4個具體的天使,我們進行抽象,抽象出瞭天使的特征,我們也可以歸納一個天使類。 通過這個過程,類就是對象的抽象。

類可以看做是一個模版,或者圖紙,系統根據類的定義來造出對象。我們要造一個汽車,怎麼樣造?類就是這個圖紙,規定瞭汽車的詳細信息,然後根據圖紙將汽車造出來。

類:我們叫做class。 對象:我們叫做Object,instance(實例)。以後我們說某個類的對象,某個類的實例。是一樣的意思。

示例1:英雄聯盟、王者榮耀中的類和對象

英雄就是類,具體的英雄,蓋倫、提莫是對象。

示例2:月餅模具和月餅

月餅模具是類,使用月餅模具制作的一個個月餅就是對象

第二節 類和對象

2.1 定義類和創建對象

做瞭關於對象的很多介紹,終於進入代碼編寫階段。本節中重點介紹類和對象的基本定義,屬性和方法的基本使用方式。

屬性(field 成員變量)

屬性用於定義該類或該類對象包含的數據或者說靜態特征。屬性作用范圍是整個類體。

在定義成員變量時可以對其初始化,如果不對其初始化,Java使用默認的值對其初始化。

數據類型 默認值
整型 0
浮點型 0.0
字符型 'u0000'
佈爾型 false
所有引用類型 null

屬性定義格式:

方法

方法用於定義該類或該類實例的行為特征和功能實現。方法是類和對象行為特征的抽象。方法很類似於面向過程中的函數。面向過程中,函數是最基本單位,整個程序由一個個函數調用組成。面向對象中,整個程序的基本單位是類,方法是從屬於類和對象的。

方法定義格式:

void代表沒有返回值;方法的作用:重用代碼,封裝功能,便於修改

【示例1】定義類,模擬人的行為:吃飯工作和休息

1) 面向對象分析OOA

從張三、李四、王五中提取出共同內容,提取一個類,人Person,包含共同的內容

靜態的特征:姓名、年齡、性別、住址

動態的行為:eat、rest、work

2) 面向對象設計OOD Design

類:Person

對象:zhangsan、lisi

讓對象完成功能

3) 面向對象編程OOP Programming

【示例2】模擬實現具體人的特征和行為

總結1:如何創建對象 Scanner input = new Scanner(http://System.in); Person person1 = new Person(); new 後面是構造方法,具體含義稍後講解

總結2:如何操作屬性:對象名.屬性名 person1.name="zhangsan"; person1.age = 23;

總結3:如何調用方法: 對象名.方法名(實參列表) person1.eat(); person1.work(); person1.rest("宿舍");

總結4:內存分配圖

1. 棧內存

1) stack memory

2) 存放局部變量、數組名,沒有默認值

3) 每調用一個方法會開辟一個棧幀,方法執行完立刻回收該棧幀,後進先出

2. 堆內存

1) heap memory

2) 存放真正的數組元素/對象內容,有默認值

3) 方法執行完畢後不會立刻釋放資源,由垃圾回收器負責回收;程序員不用操心 但時間不確定

3. 數組元素/對象成員變量的默認值

關於虛擬機內存模型的更多細節我們在面向對象一章會陸續講解,並在面向對象一章內容結束後進行系統總結。

2.2 局部變量和成員變量

類中定義的變量是成員變量,而方法中定義的變量,包括方法的參數,代碼塊中定義的變量被稱為局部變量。兩個的區別主要表現在以下幾方面:

【示例3】使用計算器完成加法運算

代碼執行的內存分配圖如下:

第三節 構造方法及其重載

3.1 構造方法

對於一個類來說,一般有三種常見的成員:屬性field、方法method、構造器constructor。這三種成員都可以定義零個或多個。

構造方法(constructor)也叫構造器,用於對象的初始化。構造器是一個創建對象時被自動調用的特殊方法,目的是對象的初始化。構造器的名稱應與類的名稱一致。Java通過new關鍵字來調用構造器,從而返回該類的實例,是一種特殊的方法。

聲明格式:

構造方法的4個要點:

  • 構造方法的方法名必須和類名一致!
  • 構造方法通過new關鍵字調用!!
  • 構造方法雖然有返回值,但是不能定義返回值類型(返回值的類型肯定是本類),不能在構造器裡使用return返回某個值。
  • 如果我們沒有定義構造方法,則編譯器會自動定義一個無參的構造方法。如果已定義則編譯器不會自動添加!

構造方法也是方法,隻不過有特殊的作用而已。與普通方法一樣,構造方法也可以重載。

【示例4】定義Dog類並模擬其操作

使用this關鍵字區分成員變量和局部變量

構造方法的重載

面試題:構造方法都有哪些調用方式?分別舉例

3.2 對象數組

對象作為方法參數:

假設某高校浴室壞瞭一間,學校安排學生分時段洗澡:上午男孩洗,下午女孩洗.浴室門口有個老頭,專門檢查學生是否在規定時間內洗澡;

學生類

屬性:姓名,性別,年齡

老頭類

屬性:

功能:通知學生洗澡時間段的功能

測試

已經學過數組瞭,但是數組元素都是基本數據類型或者String類型。學習瞭類和對象之後,可以定義數組的元素類型是更加復雜的引用引用數據類型,每個元素可以是一個具體的對象,稱為對象數組。

【示例5】使用對象數組存儲多個Student信息

oldMan代碼

測試代碼

內存分配圖入下圖所示。

第四節 方法調用

java中的數據類型

1基本數據類型 8個

2引用類型 類和對象 數組 接口 抽象類 枚舉 … …

方法調是Java開發中的基本操作。理解方法調用的內存分配過程,實參形參的傳遞過程非常必要。方法參數分為基本數據類型和引用數據類型兩種,傳遞參數有著實質的區別。

實參給形參傳遞數據有兩種方式

1按值傳遞 參數為基本數據類型

2按引用傳遞 參數為引用類型

4.1 基本數據類型的方法調用

【示例6】基本數據類型的方法參數

內存分配過程如圖所示

4.2.引用數據類型的方法調用

【示例7】引用數據類型的方法參數

內存分配過程如圖所示。

4.3 this

對象創建的過程和this的本質

構造方法是創建Java對象的重要途徑,通過new關鍵字調用構造器時,構造器也確實返回該類的對象,但這個對象並不是完全由構造器負責創建。創建一個對象分為如下四步:

1. 分配對象空間,並將對象成員變量初始化為0或空

2. 執行屬性值的顯示初始化

3. 執行構造方法

4. 返回對象的地址給相關的變量

this的本質就是“創建好的對象的地址”! 由於在構造方法調用前,對象已經創建。因此,在構造方法中也可以使用this代表“當前對象” 。

this最常的用法:

  • 調用成員變量:如果成員變量和局部變量同名,this必須書寫,用來區分兩者;如果沒有同名的局部變量,this可以不寫
  • 調用成員方法:這種情況下,this可以省略
  • 調用構造方法:使用this關鍵字調用重載的構造方法,避免相同的初始化代碼。但隻能在構造方法中用,並且必須位於構造方法的第一句。
  • this不能用於static方法中。

【示例8】this關鍵字的使用

未完待續