java對象導論

轉載於:http://blog.csdn.net/quinnnorris/article/details/56496514

(一)事物的抽象過程

人們所能解決的問題的複雜性,取決於能將事物抽象到什麼程度。

高等的數學和物理就是對事物高度的抽象。它們在那種極度抽象的層次來研究,一旦獲得大的進展,就會對我們日常生活造成極大的影響,比如愛因斯坦的相對論,它的發現對世界的影響就是巨大的。編程也是這樣,我們將一些日常事物進行抽象,抽象的水平越高,我們就越可以用簡潔的代碼去描述它。

Alan Kay曾經總結了第一個成功的面嚮對象語言、同時也是Java所基於的語言之一的Smalltalk的五個基本特性,這些特性表現了一種純粹的面向對象的設計方式:

萬物皆爲對象
程序是對象的集合,他們通過發送消息來告知彼此要做何事
每個對象都有自己的由其他對象所構成的存儲
每個對象都擁有其類型
某一特定類型的所有對象都可以接收同樣的消息

或者我們可以對對象進行更加簡潔的描述:對象具有狀態、行爲和標識。每個對象都有內部數據、方法和唯一的地址。

(二)每個對象都有自己的功能

所有的對象都是唯一的,但同時具有相同的特性和行爲的對象所歸屬的類的一部分。這就比如,天空中有很多麻雀,每個麻雀都是一個獨立的個體,但是這些個體都是麻雀,它們都有着麻雀的特性。

每個對象都是一個服務的提供者,我們可以通過調用這個對象中的方法,使用對象中的變量來進行自己的操作。將對象看作是服務提供者還有一個附帶的好處:這有助於提高對象的內聚性。高內聚是軟件設計的基本質量要求之一,這意味着一個軟件結構組織的很好,在這個類中,所有的方法和屬性都爲了一個功能而生,這些方法和屬性聚集在一起,在使用時非常便捷。但是我們在日常設計對象的時候面臨的一個問題是,我們常常將過多的功能都塞在一個對象中。
在良好的面向對象設計中,每個對象都可以很好的完成一項任務,他們並不試圖做更多的事情。這樣的設計會有這另外一個好處:低耦合。因爲每個對象都有着自己高度內聚的屬性方法,他們都爲了做自己的“分內之事”而生,多個不同類型對象間通過將各自的功能拼搭,從而達到這種低耦合的效果。

(三)封裝性——被隱藏的具體實現

在計算機網絡結構的七層模型中,各個層之間互相封閉,最終完成了從最虛擬的計算機操作到做底層的電子線路操作這整套的網絡結構。在它的層與層之間,上一層只能看得到下一層方法的接口,他只能知道如何去調用下一層的方法,而對下一層的具體代碼實現並不感興趣。
在java的代碼中,使用了三個關鍵字在類中設定邊界,這三個訪問指定詞決定了緊跟在其後的內容可以被誰使用:

public: 當前類 當前包 子孫類 其他包
protected: 當前類 當前包 子孫類
default(無修飾): 當前類 當前包
private: 當前類

(四)複用與組合

代碼的複用與組合是面向對象程序設計語言所提供的最了不起的優點之一。

最簡單的複用的方式就是:直接使用該類的一個對象。此外,也可以將那個類的一個對象至於某個新的類中,我們稱這種複用方式爲“創建一個成員對象”。新的類可以由任意數量、任意類型的其他對象以任意可以實現新的類中想要的功能的方式所組合。因爲是在使用現有的類合成新的類,所以這種概念被稱作組合。
我們通常將組合視作是擁有關係——“has-a”。

相比較很多新手非常喜歡在自己的類中使用繼承關係,實際上,在建立新類時應該首先考慮組合,因爲它更加靈活。如果採用這種組合的方式,設計會變得更加清晰。

(五)繼承

我們就不介紹繼承是什麼意思了,值得一提的是,當我們在項目中去考慮如何抽象出父類時可以思考多個子類,用多個子類來找出他們的共同點,這樣對我們抽象父類很有幫助。

因爲繼承的關係,所有可以發送給基類對象的消息同時也可以發送給子類對象。這就意味着,實際上,子類與父類具有相同的類型。如果我們只是繼承了父類,在父類中只重寫方法而不創建新的方法,我們可以稱之爲純粹替代,對於純粹替代,我們用——“is-a”來表示這種關係。對於那些不僅僅繼承了父類,而且在父類的基礎上添加了新的方法,我們用——“is-like-a”來表示這種關係。

(六)多態性與後期綁定特點

在處理層次結構時,我們經常把一個對象不作爲某個特定的對象來處理,而是作爲他們的父類來對待。比如,我們需要傳入一個列表,這時我們在方法的參數中不需區分到底是ArrayList列表還是LinkedList列表,我們只需寫上List列表即可。這種多態性讓程序極大的豐富化。

但是說到這裏存在一個最簡單卻又很難說清的問題:比如上述的方法在傳入一個列表後要調用add函數,這個方法怎麼知道傳入的List調用哪個add函數呢?

這個問題的答案,也是面向對象程序設計的最重要的妙訣:編譯器不產生傳統意義上的前期綁定的函數調用,而是採用後期綁定的方法。一個非面向對象變成的編譯器產生的函數調用會引起所謂的前期綁定,這個綁定方法意味着編譯器將產生一個具體函數名字的調用,而運行時將這個調用解析到將要被執行的代碼的絕對地址。OOP爲了解決這個問題使用了後期綁定的概念。當向對象發送消息時,被調用的代碼直到運行時才能確定。編譯器確保被調用的方法存在,並對參數返回值進行檢查,但是並不知道將被執行的確切代碼。

在C++中,必須明確的通過關鍵字virtual來聲明希望某個方法具備後期綁定屬性所帶來的靈活性,也就是說默認情況下並不是後期綁定。而在java中動態綁定是默認行爲。

(七)單根繼承結構

在java中,所有的類最終都繼承於單一的基類,這個基類就是Object。事實證明,單根繼承結構帶來了很多好處。單根繼承使得垃圾回收器的實現變得容易的多。由於所有對象都保證具有其類型信息,因此不會因無法確定對象的類型而陷入僵局。

(八)對象創建和生命週期

當談到對象的創建和生命週期時,腦海中不禁浮現出了很多種語言,這些語言對它的處理各不相同。C++認爲效率控制是最重要的議題,所以,C++給了程序員選擇的權利。可以自己new,但是必須要delete掉new出來的空間,否則會陷入著名的內存泄漏的問題之中。
在java中,所有的對象都是在堆的內存池中動態地創建的。這種方式中,知道運行時才知道需要多少對象,他們的生命週期如何,以及他們的具體類型是什麼。這樣的問題只有在程序運行時相關代碼被執行的那一刻才能確定。所以需要大量的時間在堆中分配存儲空間,這可能要遠遠大於在堆棧中創建存儲空間的時間。在堆棧中創建存儲空間和釋放存儲空間通常都僅需要一條指令。創建堆存儲空間的時間依賴於存儲機制的設計。

(九)異常處理

異常是一種對象。他從出錯地點被“拋出”。並被專門設計用來處理特定類型錯誤的相應的異常處理器“捕獲”。異常處理就像是與程序正常執行路徑並行的,在錯誤發生時執行的另一條路徑。因爲他是一條完全分離的執行路線,所以它不會干擾正常執行的代碼。

值得注意的是:異常處理不是面向對象的特徵——儘管在面嚮對象語言中異常處理常被表示成一個對象。異常處理在面嚮對象語言出現之前就已經存在了。

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