java“為什么面向?qū)ο蟮木幊虝?huì)在軟件開(kāi)發(fā)領(lǐng)域造成如此震憾的影響?”
發(fā)布時(shí)間:2008-08-06 閱讀數(shù): 次 來(lái)源:網(wǎng)樂(lè)原科技
面向?qū)ο缶幊蹋∣OP)具有多方面的吸引力。對(duì)管理人員,它實(shí)現(xiàn)了更快和更廉價(jià)的開(kāi)發(fā)與維護(hù)過(guò)程。對(duì)分析與設(shè)計(jì)人員,建模處理變得更加簡(jiǎn)單,能生成清晰、易于維護(hù)的設(shè)計(jì)方案。對(duì)程序員,對(duì)象模型顯得如此高雅和淺顯。此外,面向?qū)ο蠊ぞ咭约皫?kù)的巨大威力使編程成為一項(xiàng)更使人愉悅的任務(wù)。每個(gè)人都可從中獲益,至少表面如此。
如果說(shuō)它有缺點(diǎn),那就是掌握它需付出的代價(jià)。思考對(duì)象的時(shí)候,需要采用形象思維,而不是程序化的思維。與程序化設(shè)計(jì)相比,對(duì)象的設(shè)計(jì)過(guò)程更具挑戰(zhàn)性——特別是在嘗試創(chuàng)建可重復(fù)使用(可再生)的對(duì)象時(shí)。過(guò)去,那些初涉面向?qū)ο缶幊填I(lǐng)域的人都必須進(jìn)行一項(xiàng)令人痛苦的選擇:
(1) 選擇一種諸如Smalltalk的語(yǔ)言,“出師”前必須掌握一個(gè)巨型的庫(kù)。
(2) 選擇幾乎根本沒(méi)有庫(kù)的C++(注釋①),然后深入學(xué)習(xí)這種語(yǔ)言,直至能自行編寫(xiě)對(duì)象庫(kù)。
①:幸運(yùn)的是,這一情況已有明顯改觀?,F(xiàn)在有第三方庫(kù)以及標(biāo)準(zhǔn)的C++庫(kù)供選用。
事實(shí)上,很難很好地設(shè)計(jì)出對(duì)象——從而很難設(shè)計(jì)好任何東西。因此,只有數(shù)量相當(dāng)少的“專(zhuān)家”能設(shè)計(jì)出最好的對(duì)象,然后讓其他人享用。對(duì)于成功的OOP語(yǔ)言,它們不僅集成了這種語(yǔ)言的語(yǔ)法以及一個(gè)編譯程序(編譯器),而且還有一個(gè)成功的開(kāi)發(fā)環(huán)境,其中包含設(shè)計(jì)優(yōu)良、易于使用的庫(kù)。所以,大多數(shù)程序員的首要任務(wù)就是用現(xiàn)有的對(duì)象解決自己的應(yīng)用問(wèn)題。
抽象的進(jìn)步
所有編程語(yǔ)言的最終目的都是提供一種“抽象”方法。一種較有爭(zhēng)議的說(shuō)法是:解決問(wèn)題的復(fù)雜程度直接取決于抽象的種類(lèi)及質(zhì)量。這兒的“種類(lèi)”是指準(zhǔn)備對(duì)什么進(jìn)行“抽象”?匯編語(yǔ)言是對(duì)基礎(chǔ)機(jī)器的少量抽象。后來(lái)的許多“命令式”語(yǔ)言(如FORTRAN,BASIC和C)是對(duì)匯編語(yǔ)言的一種抽象。與匯編語(yǔ)言相比,這些語(yǔ)言已有了長(zhǎng)足的進(jìn)步,但它們的抽象原理依然要求我們著重考慮計(jì)算機(jī)的結(jié)構(gòu),而非考慮問(wèn)題本身的結(jié)構(gòu)。在機(jī)器模型(位于“方案空間”)與實(shí)際解決的問(wèn)題模型(位于“問(wèn)題空間”)之間,程序員必須建立起一種聯(lián)系。這個(gè)過(guò)程要求人們付出較大的精力,而且由于它脫離了編程語(yǔ)言本身的范圍,造成程序代碼很難編寫(xiě),而且要花較大的代價(jià)進(jìn)行維護(hù)。由此造成的副作用便是一門(mén)完善的“編程方法”學(xué)科。
為機(jī)器建模的另一個(gè)方法是為要解決的問(wèn)題制作模型。對(duì)一些早期語(yǔ)言來(lái)說(shuō),如LISP和APL,它們的做法是“從不同的角度觀察世界”——“所有問(wèn)題都?xì)w納為列表”或“所有問(wèn)題都?xì)w納為算法”。PROLOG則將所有問(wèn)題都?xì)w納為決策鏈。對(duì)于這些語(yǔ)言,我們認(rèn)為它們一部分是面向基于“強(qiáng)制”的編程,另一部分則是專(zhuān)為處理圖形符號(hào)設(shè)計(jì)的。每種方法都有自己特殊的用途,適合解決某一類(lèi)的問(wèn)題。但只要超出了它們力所能及的范圍,就會(huì)顯得非常笨拙。
面向?qū)ο蟮某绦蛟O(shè)計(jì)在此基礎(chǔ)上則跨出了一大步,程序員可利用一些工具表達(dá)問(wèn)題空間內(nèi)的元素。由于這種表達(dá)非常普遍,所以不必受限于特定類(lèi)型的問(wèn)題。我們將問(wèn)題空間中的元素以及它們?cè)诜桨缚臻g的表示物稱(chēng)作“對(duì)象”(Object)。當(dāng)然,還有一些在問(wèn)題空間沒(méi)有對(duì)應(yīng)體的其他對(duì)象。通過(guò)添加新的對(duì)象類(lèi)型,程序可進(jìn)行靈活的調(diào)整,以便與特定的問(wèn)題配合。所以在閱讀方案的描述代碼時(shí),會(huì)讀到對(duì)問(wèn)題進(jìn)行表達(dá)的話語(yǔ)。與我們以前見(jiàn)過(guò)的相比,這無(wú)疑是一種更加靈活、更加強(qiáng)大的語(yǔ)言抽象方法??傊?,OOP允許我們根據(jù)問(wèn)題來(lái)描述問(wèn)題,而不是根據(jù)方案。然而,仍有一個(gè)聯(lián)系途徑回到計(jì)算機(jī)。每個(gè)對(duì)象都類(lèi)似一臺(tái)小計(jì)算機(jī);它們有自己的狀態(tài),而且可要求它們進(jìn)行特定的操作。與現(xiàn)實(shí)世界的“對(duì)象”或者“物體”相比,編程“對(duì)象”與它們也存在共通的地方:它們都有自己的特征和行為。
Alan Kay總結(jié)了Smalltalk的五大基本特征。這是第一種成功的面向?qū)ο蟪绦蛟O(shè)計(jì)語(yǔ)言,也是Java的基礎(chǔ)語(yǔ)言。通過(guò)這些特征,我們可理解“純粹”的面向?qū)ο蟪绦蛟O(shè)計(jì)方法是什么樣的:
(1) 所有東西都是對(duì)象。可將對(duì)象想象成一種新型變量;它保存著數(shù)據(jù),但可要求它對(duì)自身進(jìn)行操作。理論上講,可從要解決的問(wèn)題身上提出所有概念性的組件,然后在程序中將其表達(dá)為一個(gè)對(duì)象。
(2) 程序是一大堆對(duì)象的組合;通過(guò)消息傳遞,各對(duì)象知道自己該做些什么。為了向?qū)ο蟀l(fā)出請(qǐng)求,需向那個(gè)對(duì)象“發(fā)送一條消息”。更具體地講,可將消息想象為一個(gè)調(diào)用請(qǐng)求,它調(diào)用的是從屬于目標(biāo)對(duì)象的一個(gè)子例程或函數(shù)。
(3) 每個(gè)對(duì)象都有自己的存儲(chǔ)空間,可容納其他對(duì)象?;蛘哒f(shuō),通過(guò)封裝現(xiàn)有對(duì)象,可制作出新型對(duì)象。所以,盡管對(duì)象的概念非常簡(jiǎn)單,但在程序中卻可達(dá)到任意高的復(fù)雜程度。
(4) 每個(gè)對(duì)象都有一種類(lèi)型。根據(jù)語(yǔ)法,每個(gè)對(duì)象都是某個(gè)“類(lèi)”的一個(gè)“實(shí)例”。其中,“類(lèi)”(Class)是“類(lèi)型”(Type)的同義詞。一個(gè)類(lèi)最重要的特征就是“能將什么消息發(fā)給它?”。
(5) 同一類(lèi)所有對(duì)象都能接收相同的消息。這實(shí)際是別有含義的一種說(shuō)法,大家不久便能理解。由于類(lèi)型為“圓”(Circle)的一個(gè)對(duì)象也屬于類(lèi)型為“形狀”(Shape)的一個(gè)對(duì)象,所以一個(gè)圓完全能接收形狀消息。這意味著可讓程序代碼統(tǒng)一指揮“形狀”,令其自動(dòng)控制所有符合“形狀”描述的對(duì)象,其中自然包括“圓”。這一特性稱(chēng)為對(duì)象的“可替換性”,是OOP最重要的概念之一。
一些語(yǔ)言設(shè)計(jì)者認(rèn)為面向?qū)ο蟮某绦蛟O(shè)計(jì)本身并不足以方便解決所有形式的程序問(wèn)題,提倡將不同的方法組合成“多形程序設(shè)計(jì)語(yǔ)言”(注釋②)。
②:參見(jiàn)Timothy Budd編著的《Multiparadigm Programming in Leda》,Addison-Wesley 1995年出版。
1.2 對(duì)象的接口
亞里士多德或許是認(rèn)真研究“類(lèi)型”概念的第一人,他曾談及“魚(yú)類(lèi)和鳥(niǎo)類(lèi)”的問(wèn)題。在世界首例面向?qū)ο笳Z(yǔ)言Simula-67中,第一次用到了這樣的一個(gè)概念:
所有對(duì)象——盡管各有特色——都屬于某一系列對(duì)象的一部分,這些對(duì)象具有通用的特征和行為。在Simula-67中,首次用到了class這個(gè)關(guān)鍵字,它為程序引入了一個(gè)全新的類(lèi)型(clas和type通??苫Q使用;注釋③)。
③:有些人進(jìn)行了進(jìn)一步的區(qū)分,他們強(qiáng)調(diào)“類(lèi)型”決定了接口,而“類(lèi)”是那個(gè)接口的一種特殊實(shí)現(xiàn)方式。
Simula是一個(gè)很好的例子。正如這個(gè)名字所暗示的,它的作用是“模擬”(Simulate)象“銀行出納員”這樣的經(jīng)典問(wèn)題。在這個(gè)例子里,我們有一系列出納員、客戶、帳號(hào)以及交易等。每類(lèi)成員(元素)都具有一些通用的特征:每個(gè)帳號(hào)都有一定的余額;每名出納都能接收客戶的存款;等等。與此同時(shí),每個(gè)成員都有自己的狀態(tài);每個(gè)帳號(hào)都有不同的余額;每名出納都有一個(gè)名字。所以在計(jì)算機(jī)程序中,能用獨(dú)一無(wú)二的實(shí)體分別表示出納員、客戶、帳號(hào)以及交易。這個(gè)實(shí)體便是“對(duì)象”,而且每個(gè)對(duì)象都隸屬一個(gè)特定的“類(lèi)”,那個(gè)類(lèi)具有自己的通用特征與行為。
因此,在面向?qū)ο蟮某绦蛟O(shè)計(jì)中,盡管我們真正要做的是新建各種各樣的數(shù)據(jù)“類(lèi)型”(Type),但幾乎所有面向?qū)ο蟮某绦蛟O(shè)計(jì)語(yǔ)言都采用了“class”關(guān)鍵字。當(dāng)您看到“type”這個(gè)字的時(shí)候,請(qǐng)同時(shí)想到“class”;反之亦然。
建好一個(gè)類(lèi)后,可根據(jù)情況生成許多對(duì)象。隨后,可將那些對(duì)象作為要解決問(wèn)題中存在的元素進(jìn)行處理。事實(shí)上,當(dāng)我們進(jìn)行面向?qū)ο蟮某绦蛟O(shè)計(jì)時(shí),面臨的最大一項(xiàng)挑戰(zhàn)性就是:如何在“問(wèn)題空間”(問(wèn)題實(shí)際存在的地方)的元素與“方案空間”(對(duì)實(shí)際問(wèn)題進(jìn)行建模的地方,如計(jì)算機(jī))的元素之間建立理想的“一對(duì)一”對(duì)應(yīng)或映射關(guān)系。
如何利用對(duì)象完成真正有用的工作呢?必須有一種辦法能向?qū)ο蟀l(fā)出請(qǐng)求,令其做一些實(shí)際的事情,比如完成一次交易、在屏幕上畫(huà)一些東西或者打開(kāi)一個(gè)開(kāi)關(guān)等等。每個(gè)對(duì)象僅能接受特定的請(qǐng)求。我們向?qū)ο蟀l(fā)出的請(qǐng)求是通過(guò)它的“接口”(Interface)定義的,對(duì)象的“類(lèi)型”或“類(lèi)”則規(guī)定了它的接口形式?!邦?lèi)型”與“接口”的等價(jià)或?qū)?yīng)關(guān)系是面向?qū)ο蟪绦蛟O(shè)計(jì)的基礎(chǔ)。