天天看點

Java 程式設計思想 讀書筆記第一章 對象導論

第一章 對象導論

一、抽象過程

所有程式設計語言都提供抽象機制,人們所能解決的問題的複雜性直接取決于抽象的類型和品質。

1.1 隻針對問題來進行模組化

早期:基于限制條件程式設計的語言和通過圖形符号操作來實作的程式設計語言常常在領域更替後就變得寸步難行。

面向對象

面向對象的方式通過向程式員提供表示問題空間元素的工具。–對象
這種思想的實質就是,程式員可以添加新類型的對象來使自身适用于某個特定的問題
對象具有狀态、行為、辨別,每個對象都可以擁有内部資料和方法,并且每一個對象都可以唯一的與其他對象區分開,每個對象在記憶體中都有一個唯一的位址

二、每一個對象都有一個接口

盡管所有的對象都是唯一的,但同時也是具有相同特性(内部資料)和行為(方法)的對象所歸屬的類的一部分

2.1 銀行出納員問題

第一個面向對象語言:Simula

銀行出納員問題:

可以形成對象對象:出納,客戶賬戶,交易和貨币機關

執行期間:具有不同狀态,但是其他方面相似的對象會分組到對象的類中

**建立抽象資料類型(類)是面向對象程式設計的基本概念之一**

可以建立某一類型的變量(對象、執行個體),然後操作這些變量(告訴對象要做什麼)

每個類的成員或者元素都具有某種共性:

每個賬戶:結餘金額(元素)

每個出納:都有處理存款方法

、、、

是以:出納,客戶、賬戶、交易都可以表示為一個實體,這個實體就叫對象,每個對象屬于某個具有特定行為和元素的類
           

2.2 小總結

面向程式設計實際進行的就是建立一個新的類型:class

程式員通過建立不同的類,來适應問題,而不再被迫用表示機器存儲單元的資料類型。

2.3 如何擷取有用的對象?

有某種方式産生對對象的請求,使對象完成各種任務。
某個對象隻能滿足某些請求,這些請求由對象的接口所定義,決定接口的便是類型。

接口确定了對某一特定對象所能發出的請求。

但是,程式中必須有滿足這些請求的代碼,這些代碼與隐藏的資料一同構成了實作,請求與方法關聯,發起一個請求,一個關聯的方法就會被調用。

三、每個對象都提供服務

試圖開發或者了解一個程式設計,最好的方法之一就是将對象當作服務的提供者。
程式本身将向使用者提供服務,他通過調用其他對象提供的服務來實作這一目的。
你的目标就是去建立能夠提供理想服務的對象來解決問題。

3.1 将對象看作是服務提供者的好處:有利于提高對象的内聚性

這裡的舉例是一個列印子產品

可以設計一個對象了解所有的格式和列印技術,但對這個對象來說會使他很臃腫。

也可以設計一個對象,是所有的可能的支票排版目錄,用來查詢有關如何列印一張支票的資訊,另一個對象可以是通用的列印接口,他知道所有不同類型的列印機的資訊,第三個對象通過調用另外兩個對象的服務來完成列印工作。這樣每個對象都有一個他所能提供服務内聚的集合。

在良好的面向對象程式設計中,每個對象都可以很好的完成一項任務,但他不試圖做更多的事。

四、被隐藏的具體實作

将程式開發人員按照角色分為類建立者(建立新資料類型的程式員)和用戶端程式員(哪些在其應用中使用資料類型的類消費者)是大有好處的。
類建立者的目标是建構類:他們建構的類,隻向用戶端程式員暴露必須的部分,而隐藏其他部分。
用戶端程式員:收集各種用來實作快速應用開發的類。

4.1 通路控制存在的原因

第一存在原因:讓用戶端程式員無法觸及他們不應該觸及的部分。
第二存在原因:允許庫設計者可以改變類内部的工作方式而不用擔心會影響到用戶端程式員

4.2 關鍵字

Java用三個關鍵字來在類的内部設定邊界:public,private,protected
public:緊随其後的元素對任何人都是可用的
private:除類型建立者和類型的内部方法之外的任何人都不能通路的元素
protected:與private作用相當,差别在于繼承該類的類可以通路protected成員
預設的通路權限:前面沒有寫任何指定詞,同一個包中的其他類成員可以通路,但是包之外就像加了private一樣,包内像public

五、複用具體展現

代碼複用是面向對象程式設計語言所提供的最了不起的優點之一。
最簡單的複用某個類的方式:直接使用該類的一個對象,新的類可以由任意數量,任意類型的其他對象以任意可以實作新的類中想要的功能的方式所組成。
使用現有的類産生新的類,這種方式成為組合,如果組合是動态發生的,我們稱之為聚合
組合帶來極大的靈活性,新類的成員對象通常被聲明為private,使得新類的用戶端程式員不能通路他們,這也使得你可以在不幹擾現有用戶端代碼的情況下,修改這些成員,也可以在運作時修改這些成員獨享,以實作動态修改程式的行為。
在建造新類的時候,首先應該考慮的是組合而不是繼承,他更加靈活,而且因為過度的使用繼承來導緻程式過度設計,繼承應當合理的使用,而不是盲目地使用

六、繼承(有點複雜,反複回味)

對象:本身就是十分友善的工具,使得我們可以通過概念将資料與功能封裝在一起。由此可以對問題空間的概念給出恰當的表示,而不用被底層機器語言限制,這種概念由class關鍵字來表示,形成了程式設計語言的基本機關。

6.1 為什麼需要繼承?

如果隻有對象的概念,不斷地建立新的對象存在的缺點:容易創造出相似的類,比如兩個類明明很相似,還需要反複創作新類。不如創作一個類為基礎,複制他,通過添加和修改這個副本來建立新類,不過當源類被修改時,副本類也會有相應的變動
類型不僅僅知識描述作用于一個對象集合的限制條件,同時還有與其他類型之間的關系,兩個類型之間可以存在相同的特性與行為,但其中一個比另一個有更多的特性,并且還可以處理更多消息。
繼承使用基類和導出類的概念表示這種類型之間的相似性。一個基類包括所有導出類型所共享的特性和行為。

6.2 繼承的舉例

可以建立一個基類型來表示系統中某些對象的核心概念,從基類型中導出其他的類型,來表示此核心可以被實作的各種不同的方式
一,垃圾分類的例子:雖然垃圾都成為垃圾,但是分類的不同垃圾有其不同的特性,垃圾隻是他們的總稱

6.3 類型的等價性

可以通過使用繼承來建構一個類型層次結構,以此來表示待求解的某種類型的問題,類型的層次結構同時展現出不同的類的相似性和差異性。
當繼承現有類型時,也就創造了新的類型,新的類型不僅包括了現有類型的所有成員,而且更重要的是他複制了基類的接口。其意思也可以了解為,所有發送給基類對象的消息同時也可以發送給導出類對象。
導出類複制了基類的方法
發送給基類的方法==》也可以發送給導出類
由:發送給類的消息的類型可以知道類的類型
==》基類類型 = 導出類類型
由于通過發送給類的消息的類型可知類的類型,這也就意味着導出類與基類具有相同的資料類型。通過繼承而産生類型的等價性,是了解面向對象設計方法内涵的重要門檻。

6.4 基類與導出類産生差異

基類與導出類産生差異的方法:兩種
一、直接在導出類中添加新方法
二、在導出類中覆寫基類中的方法

6.5 is-a(是一個) 、is-like-a(像是一個)

讨論:繼承應該隻覆寫基類的方法?
如果這樣做,意味着導出類和基類是完全相同的類型,因為他們有完全相同接口,可以用一個導出類對象完全替代一個基類對象,這可以被視為純粹替代,通常稱之為替代原則。某些情況下,這是處理繼承的理想方式。這種情況下的基類與導出類之間的關系稱為 is-a關系,判斷是否繼承,就是要确定是否可以用is-a來描述類之間的關系。
有時必須在導出類型中添加新的接口元素,這樣就拓展了接口,這個類型仍然可以替換基類,但這種替換是不完全的,因為基類無法通路新添加的方法,這種情況我們稱之為is-like-a。

七、伴随多态的可互換對象

在處理類型的層次結構時,經常會把一個對象不當作他所屬的特定類型來處理,而是将其當作基類的對象來對待。這種方式使得人們不依賴于特定類型的代碼。
通過導出新的子類型而輕松擴充設計的能力是對改動進行封裝的基本方式之一

7.1 遇到的問題

但是在試圖将導出類性的對象,當作其泛化基類型對象來看待時(圓形當作幾何形處理,自行車當作交通工具),因為基類型有多個繼承類,編譯器不知道在編譯時該執行哪一段代碼。

7.2 問題該如何解決

上述問題的答案,也是面向對象程式設計的最重要的秘訣:
編譯器不可能産生傳統意義上的函數調用。
  • 非面向對象的編譯器處理方法:

一個非面向對象程式設計的編譯器産生的函數調用會引起所謂的前期綁定,這麼做意味着編譯器将産生對一個具體的函數名字的調用,而運作時将這個調用解析到将來要被執行的代碼的絕對位址。
  • 面向對象的處理

但是在oop中,程式知道運作時才能夠确定代碼的位址,是以當消息發送到一個泛化對象時,必須采用其他的機制
面向對象的程式設計語言:後期綁定
當向對象發送消息時,被調用的代碼直到運作時才能确定。
編譯器確定被調用的方法的存在,并對調用參數和傳回值執行類型檢查,但并不知道将被執行的确定的代碼。
為了執行後期綁定,Java使用一小段特殊的代碼來替換絕對位址調用,這段代碼使用在對象中存儲的資訊來計算方法體的位址,根據這一小段代碼的内容,每一個對象可以具有不同的行為表現。當對象發送消息時,該對象能夠知道這條消息應該做些什麼。

7.3 自己寫的小案例(圖檔丢了,還是截書裡的吧)

Java 程式設計思想 讀書筆記第一章 對象導論
doSomething(Shape shape)方法可以與任何Shape對話,當Line被傳入Shape中,由于Line和Circle都是Shape的字類,doSomething(Shape shape)可以發送給Shape的任何消息,Line都可以接收。

7.4 向上轉型

Java 程式設計思想 讀書筆記第一章 對象導論
向上轉型:把導出類看作是它的基類的過程
向上:繼承圖中的典型布局,基類在頂部,導出類向下散開,所有由此而來
轉型:模型鑄造的塑膜動作

八、單根繼承結構

8.1 問題:是否所有的類最終都繼承自單一的基類

C++:no
Java:yes 均繼承類Object

8.2 單根繼承的優勢

C++無法保證所有的對象都屬于一個基本資料類型,從向後相容的角度看,這麼做可以更好地适應C模型,但進行完全的面向對象程式設計時,則必須建構自己的體系,使得C++享受不到面向對象語言的周遊,需要自己去設計,進而極大的降低了生産率。
單根繼承結構的所有對象都具備某些功能。,可以在每個對象中執行一些基本操作,所有的對象都很容易在堆上建立,參數傳遞也得到了極大簡化。
單根繼承也使得垃圾回收器的實作更加容易,而垃圾回收器正是Java與C++的重大改進之一。由于所有的對象都保證具有其類型資訊,是以不會因為無法确定對象的類型而陷入僵局,這對系統級别的操作,如異常處理顯得尤其重要,并且給程式設計帶來了更大的靈活性。

九、容器

9.1 容器概述

滿足不同需要的各種類型的容器:List,Map,Set等

容器被設計得多樣化的原因:

不同的容器提供了不同類型的接口和外部行為

不同的容器對于某些操作具有不同得效率

9.2 參數化類型

因為Java的單根繼承,容器中存儲對象,在存儲時的複用性來源于所有的類都繼承自object,但是容器不隻有存儲,還有取出,我們可以知道存儲的過程是,某一類型向上轉型為object,這是安全的,但是取出時是将某一object類型轉換為具體類型,我們稱之為向下轉型,但向下轉型就存在危險了,你無法确定需要将其轉換為什麼類型,向下轉型如果轉為錯誤的類型就會得到運作時錯誤,是以在取出集合時要利用某種方式記住這些對象是什麼類型的。
這時就需要建立出一個容器,他知道自己所儲存的對象的類型,這種方式就叫做參數化類型機制,參數化類型就是一個編譯器可以自動定制作用域特定類型上的類。
Java 5 增加了參數化類型:泛型

十、對象的建立和生命期

在使用對象時間,最關鍵的問題之一是他們的生成和銷毀方式,每個對象為了生存都需要資源,尤其是記憶體,是以在我們不需要一個對象的時候,它必須被清理掉,使其占有的資源可以被釋放和重用。

10.1 問題一

對象的資料位于何處?怎樣控制對象的生命周期?
C++的實作方式,他認為效率應該排在第一位,是以他給程式員提供了選擇的權力。為了追求更大的執行速度,對象的存儲空間和生命周期可以在編寫程式時确定,這可以通過将對象置于堆棧或靜态存儲區域内來實作。這種方式将存儲空間配置設定和釋放放置于優先考慮的位置。某些情況下很有價值,但在一些情況下顯得太不靈活了,因為在編寫程式時就要知道對象的确切的數量,生命周期和類型。
其他的實作方式:在稱為堆的記憶體池中動态的建立對象,在這種方式中,直到運作時才知道需要多少對象,他們的生命周期如何,以及他們具體的類型是什麼。這些問題隻有在程式運作時,相關代碼被執行到的時候才會确定,如果需要一個新的對象,可以在需要的時刻,直接在堆中建立。
存儲空間在運作時被動态管理
需要大量的時間在堆中配置設定存儲空間,遠大于在堆棧中建立存儲空間的時間,在堆棧中建立和釋放存儲空間通常各需要一條彙編指令就可以了,分别将對應的棧頂指針向下移動(我感覺是上)或向上(我感覺是下)移動,(有大佬看到可以幫我解釋一下為什麼嗎?)建立存儲空間的時間依賴于存儲機制的設計。·
動态方式有一個一般性的邏輯假設:對象趨向于變得複雜,是以查找和釋放存儲空間的開銷不會對對象的建立造成重大沖擊,動态方式所帶來的靈活性是解決一般程式設計問題的要點所在。
Java完全采用動态程式設計的方式,需要建立新的對象的時候就需要new新的動态執行個體。

10.2 銷毀問題

那麼還有一個問題:如果在堆上來建立對象,又将在什麼時候将對象銷毀呢?在堆棧上建立對象的語言,編譯器可以确定對象的存活時間,并可以自動銷毀他。
Java垃圾回收器:被設計用來處理記憶體釋放問題,盡管他不包括清理對象的其他方面,垃圾回收器“知道”對象何時不再使用,并自動釋放對象占用的記憶體。

10.3 Java、小Tips

兩個特性:
所有對象都繼承自單根基類Object
所有對象隻能以一種方式建立對象,在堆上建立。

十一、異常處理:處理錯誤

Java内置了異常處理,而且強制你必須使用他

十二、并發程式設計

在計算機程式設計中有一個基本概念,就是同一時刻處理多個任務的思想。許多程式設計問題都要求,程式能夠停下正在做的事情,轉而處理其他的問題,然後再來處理主程式。
線程隻是一種為單一處理器配置設定執行時間的手段。如果作業系統支援多處理器,那麼每個任務都可以指派給不同的處理器,他們是真正的并行執行的。
隐患:共享資源,如果多個并行任務都要通路統一資源,就會出問題,比如公用列印機,一方用的時候就要将列印機鎖定,不能同時用,整個過程:某個任務鎖定某資源,完成任務,釋放鎖,使其他任務能使用這項資源

十三、Java與Internet

待辦

十四、總結

待辦