精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

面向?qū)ο缶幊獭惻c對象

AGk5_ZLG_zhiyua ? 來源:未知 ? 作者:佚名 ? 2017-09-27 15:36 ? 次閱讀

周立功教授數(shù)年之心血之作《程序設(shè)計(jì)與數(shù)據(jù)結(jié)構(gòu)》以及《面向AMetal框架與接口編程(上)》,電子版已無償性分享到電子工程師與高校群體,書本內(nèi)容公開后,在電子行業(yè)掀起一片學(xué)習(xí)熱潮。經(jīng)周立功教授授權(quán),本公眾號特對《程序設(shè)計(jì)與數(shù)據(jù)結(jié)構(gòu)》一書內(nèi)容進(jìn)行連載,愿共勉之。

第四章為面向?qū)ο缶幊?/span>,本文為4.2 類與對象。

4.2 類與對象

亞里士多德可能是第一個研究類型概念的人,他提到了“魚類和鳥類”。將具有共同的行為和特征的所有對象歸為一個類的思想,在第一個面向?qū)ο笳Z言Simula-67中得到了直接應(yīng)用,其目的是為了解決模擬問題。比如,銀行的出納業(yè)務(wù),包括出納部門、顧客、業(yè)務(wù)、貨幣的單位等大量的對象,將具有相同數(shù)據(jù)結(jié)構(gòu)(屬性)和行為(操作)的對象歸在一起為一個類,屬于類的任何對象都共享該類的所有屬性,這就是類的來源。

創(chuàng)建抽象數(shù)據(jù)類型是OOP的基本思想,幾乎能象完全內(nèi)建類型一樣使用。程序員可以創(chuàng)建類型的變量和操作這些變量。每個類的成員都有共性,每個賬戶有余額,每個出納員都能接收存款等。同時每個成員都有自己的狀態(tài),每個賬戶有不同的余額,每個出納員都有名字。通常在計(jì)算機(jī)中出納員、客戶、賬戶和交易等都被描述為唯一的實(shí)體,這個實(shí)體就是對象,每個對象都屬于一個定義了它的行為和特性的特定類。

由此可見,類和類的對象不是相同的概念,與圖紙和建筑的關(guān)系類似,對象的描述依賴描述它的類。因此可以通過創(chuàng)建類的實(shí)例創(chuàng)建對象,即定義類的變量,這個過程叫做實(shí)例化。

>>>4.2.1對象

從人類認(rèn)知的抽象角度來看,對象可以是下列事物之一:

  • 一個可以觸摸或可以看見的東西;

  • 在智力上可以理解的東西;

  • 可以指導(dǎo)思考或行動的東西。

顯而易見,一個對象反映了某一部分的真實(shí)存在,因此對象是在時間和空間中存在的某種東西。軟件中的“對象”術(shù)語首先出現(xiàn)在Simula語言中,對象存在于Simula程序中,用于模擬現(xiàn)實(shí)世界的某個方面。

某些對象可能有明確的概念邊界,但代表的是不可觸摸的事件或過程。比如,一個立方體和一個球相交,它們的相交線是一條不規(guī)則的曲線。雖然它離開了球體或立方體就不存在了,但這條線仍然是一個對象,因?yàn)樗忻鞔_定義的概念邊界。

某些對象可能是可觸摸的,但物理邊界不太清晰。比如,河流、霧和人群等就屬于這種類型的對象。雖然類似于美和色彩這樣的屬性不是對象,愛和恨這樣的感情也不是對象,但這些東西有可能成為其它對象的屬性,比如,一個男人(一個對象)愛他的妻子(另一個對象),或者說某只貓(又一個對象)是灰色的。由此可見,屬性表示對象記憶的信息,且只能通過對象的操作來訪問和修改。

當(dāng)傳統(tǒng)的過程模塊或函數(shù)返回調(diào)用者時,不會帶來任何副作用,模塊運(yùn)行結(jié)束,只將其結(jié)果返回。當(dāng)同一模塊再次被調(diào)用時,就象是第一次誕生一樣。模塊對以前的存在沒有任何記憶,就象人類一樣對以前的存在一無所知。

就對象而言,對象的一個重要特征是它們充當(dāng)數(shù)據(jù)的容器,因此對象具有記憶功能,對象知道它的過去,通常也將包含在對象屬性中的數(shù)據(jù)值稱為對象的狀態(tài)。當(dāng)一個對象的調(diào)用者給該對象一個信息后,如果該調(diào)用者或其它調(diào)用者要求該對象再次提供這一信息,則該對象執(zhí)行結(jié)束后并沒有死,因此對象具有如何保持其狀態(tài)(狀態(tài)即對象擁有值的集合)的能力。

假設(shè)你在看一個人,肯定會將這個人當(dāng)作一個對象。顯然,每個人都有數(shù)據(jù),比如,name、birthdate和weight等;一個人還有行為,比如,走路、說話和呼吸等,因此可以說對象是由“數(shù)據(jù)和行為”構(gòu)成的。在現(xiàn)實(shí)世界里,由于每個對象的狀態(tài)不一樣,因此可以用存儲在一個對象中的數(shù)據(jù)表示對象的狀態(tài),數(shù)據(jù)包含了能夠區(qū)分不同對象的信息。

在OO程序設(shè)計(jì)中,每個對象都有唯一的標(biāo)識,標(biāo)識是一個對象的屬性,用于區(qū)分這個對象與其它所有對象。而這個唯一的標(biāo)識可以通過句柄機(jī)制提供,因此可以借助這個句柄引用對象。不同的語言實(shí)現(xiàn)句柄的方式不一樣,比如,地址、數(shù)組下標(biāo)或人為編號。

在現(xiàn)實(shí)世界中一些對象有對等物,比如,ZLG公司,另一些對象則是概念實(shí)體,比如,解一元一次方程,還有一些其它的對象,比如,棧、數(shù)組變量名a,都是為了實(shí)現(xiàn)而引入的,沒有對應(yīng)的物理實(shí)體。

許多開發(fā)人員可能會認(rèn)為“一個包含了另一個對象的對象”,其本質(zhì)上與“一個具有純數(shù)據(jù)成員的對象”是完全不同的,但是那些看起來不是對象的數(shù)據(jù)成員實(shí)際上也是對象,比如,整數(shù)和雙精度數(shù)。在真正的面向?qū)ο笳Z言中,萬事萬物都是對象,甚至內(nèi)置數(shù)據(jù)也是對象,即使其行為只是運(yùn)算。

由此可見,雖然對象是具有明確定義的邊界的東西,但還不足以區(qū)分不同的對象。因?yàn)橥粋€類的每個對象具有不同的句柄,在任何特定時刻,每個對象可能有不同的狀態(tài)(指存儲在變量中的不同的“值”),因此對象是一個具有狀態(tài)、行為和標(biāo)識的實(shí)體。

對象又分持久對象和主動對象,持久對象是指生存期可以超越程序的執(zhí)行時間,而長期存在的且所有的操作都是被動執(zhí)行的對象。在主動對象概念出現(xiàn)之前,人們所理解的對象概念只是被動對象,即對象的每個操作都是被動地響應(yīng)從外部發(fā)來的消息才可以執(zhí)行。

在開發(fā)一個具有多任務(wù)并發(fā)執(zhí)行的系統(tǒng)時,如果僅有被動對象的概念,則很難描述系統(tǒng)中的多個任務(wù)。其實(shí)并發(fā)不僅僅存在操作系統(tǒng)中,如今多個任務(wù)并發(fā)可以說無處不在。每個任務(wù)在實(shí)現(xiàn)時應(yīng)該成為一個可以并發(fā)執(zhí)行的主動程序單位,那么如何描述呢?

如果用被動對象將無法描述那些不接收任何消息也要主動工作的對象,比如,交通燈控制系統(tǒng)中的信號燈,溫控器中的傳感器,它們的行為都是主動發(fā)起的,即主動對象至少有一個操作不需要接收消息就就能主動執(zhí)行的對象。

盡管發(fā)現(xiàn)對象的活動是從具體事物出發(fā)分析和認(rèn)識問題的,但人們在進(jìn)行這種活動時實(shí)際上并不局限于對個別事物的認(rèn)識,而是尋找一類事物的共同特征,將對象抽象為類。

>>>4.2.2 類

類的概念早在柏拉圖之前就出現(xiàn)了,面向?qū)ο缶幊叹拖癜乩瓐D之后的西方哲學(xué)家一樣延續(xù)了這種思維。類的概念與對象的概念是緊密交織在一起,因?yàn)樵谟懻撘粋€對象時不得不提到它的類,但是這兩個術(shù)語又存在重要的差別。對象是存在于時間和空間中的具體實(shí)體,而類僅代表一種抽象,因此可以說Validator類代表了所有校驗(yàn)器的共同特征。要確定這個類中的某個具體的校驗(yàn)器,則必須說“范圍值校驗(yàn)器”或“奇偶校驗(yàn)器”。

在面向?qū)ο蠓治雠c設(shè)計(jì)的上下文中,將類定義為——類是對現(xiàn)實(shí)世界中事物的描述,類描述了擁有相同屬性、行為和關(guān)系類別的一組對象,一個對象就是類的一個實(shí)例,因此沒有共同的屬性和行為的對象不能劃分為一個類。比如,一個相當(dāng)高層的抽象,一個GUI框架,一個數(shù)據(jù)庫和整個系統(tǒng)在概念上都是獨(dú)立的對象,因此不能將它們表示為一個單獨(dú)的類。相反應(yīng)該將這些抽象表示為一組類,通過這些類的實(shí)例互相協(xié)作,提供我們期望的功能。

通常將這樣的一組類稱為一個組件,而組件是預(yù)先創(chuàng)建好的程序模塊,可與其它模塊一起構(gòu)成一個程序。通常組件以二進(jìn)制形式發(fā)布,其實(shí)現(xiàn)對使用者來說是隱藏的。如果組件設(shè)計(jì)良好,使用者甚至不需要知道這個組件使用什么語言編寫的。但組件必須至少暴露一個接口才能使用,通常組件會有暴露多個接口。從使用者的角度來看,一個組件是一些前端接口的后端服務(wù)者,程序員通過組件接口所暴露的函數(shù)操作該組件。由此可見,組件擴(kuò)展了面向?qū)ο笾袑ο笞鳛榉?wù)提供者通過高層接口提供服務(wù)的概念。

在現(xiàn)實(shí)世界里,餅干也是對象,必須先有模子(類),才能做出你想要的形狀的餅干,因此可以認(rèn)為類是對象的模板。比如,只有符合一定條件的數(shù)值才能push到棧中,那么Validator校驗(yàn)器類就是由RangeValidator范圍值校驗(yàn)器類、OddEvenValidator奇偶校驗(yàn)器類和PrimerValidator質(zhì)數(shù)校驗(yàn)器類等具體校驗(yàn)器類的對象構(gòu)成的一個集合體。屬于類的任何對象都共享該類的所有屬性,比如,所有的具體校驗(yàn)器都有這樣的屬性——校驗(yàn)參數(shù)

在OO程序設(shè)計(jì)中,一個類就是一種抽象數(shù)據(jù)類型,用戶也可以創(chuàng)建一個自己的類,而且可以將這個類當(dāng)做數(shù)據(jù)類型使用。一旦有了類,就可以象使用普通的數(shù)據(jù)類型那樣用類定義變量,如果定義了RangeValidator類,即可用它定義變量rangeValidator。RangeValidator類的變量rangeValidator可以擁有成員變量或域,代表不同校驗(yàn)器的屬性或特性,通常將這些成員變量稱為數(shù)據(jù)成員。

(1)值和屬性

值是一段數(shù)據(jù),屬性描述了類的每個對象都擁有的一個值,可以這樣類比——對象之于類如同值之于屬性。比如,name、birthdate和weight都是Person對象的屬性,color、modelYear和weight都是Car對象的屬性。對于每個對象,每個屬性都有一個值,比如,對象ZhangSan的屬性birthdate的值是“21 October 1983”,也就是說,ZhangSan生于1983年10月21日。對于一個特定的屬性,不同的對象可能會有相同或不同的取值。在一個類中,雖然每個屬性的名字都是唯一的,但在所有的類中不一定是唯一的,比如,類Person和類Car都可能有一個名為weight的屬性。

下面將介紹一種通過屬性詳細(xì)描述類的UML建模語言,一種用于可視化表示、指定、構(gòu)造和描述軟件密集系統(tǒng)中部件的圖形化語言,它提供了一種以圖形化方式表示和管理面向?qū)ο筌浖到y(tǒng)的方法。其不僅是系統(tǒng)設(shè)計(jì)的表示,而且是一種有助于完成系統(tǒng)設(shè)計(jì)的工具。類圖定義了3個不同的部分,即類名、屬性和方法,用于解釋所構(gòu)建的類。當(dāng)用UML創(chuàng)建對象模型時,盡可能不要在類圖中包含太多的信息,這樣就能集中注意力于整體設(shè)計(jì),而不會將重點(diǎn)放在細(xì)節(jié)上。

如圖 4.1所示展示了類建模表示法,顯示了一個類(左圖)和它所描述的對象(右圖),對象ZhangSan和LiMing都是類Person的實(shí)例。對象的UML表示法是一個方框,方框里面是對象名后加冒號和類名,對象名和類名都有下劃線,并約定用黑體字表示對象名和類名。類的UML表示法也是一個方框,也約定用黑體字表示類名,將名字放在方框的正中央,首字符大寫,且用單數(shù)名詞表示類名。類Person有屬性name和birthdate,name是string(字符串),birthdate是date(日期)。類Person中一個對象的名字取值是"Zhang San",生日取值是“21 October 1983”;另一個對象的名字取值是"Li Ming",生日取值是“16 March 1950”。

圖 4.1 屬性和值的UML表示法

UML表示法會在框的第二格里列舉屬性,每個屬性后面都可以有可選項(xiàng),比如,類型和默認(rèn)值。在類之前有一個冒號,在默認(rèn)值之前有一個等號。約定以常規(guī)字體顯示屬性名,方框中的名稱左對齊,首字母使用小寫。在對象方框的第二格里,也可能會包含屬性值,其表示法是列出每個屬性名,之后跟著等號和取值,同樣屬性值也是左對齊,使用常規(guī)字體。雖然有些實(shí)現(xiàn)要求對象有唯一的標(biāo)識符,但這些標(biāo)識符在類模型中是隱含的,即不需要也不應(yīng)該顯式地將它們列舉出來,比如,PersonID:ID。因?yàn)榇蠖鄶?shù)OO開發(fā)語言會自動生成標(biāo)識符,可以使用這些標(biāo)識符來引用對象;反之,則可能需要顯式地列舉出來,否則無法引用對象。但是不要將內(nèi)部標(biāo)識符和現(xiàn)實(shí)世界的屬性混淆了,內(nèi)部標(biāo)識符純粹是一種便于實(shí)現(xiàn)的做法,沒有應(yīng)用意義。相反,納稅人編號、汽車牌照號碼和電話號碼都不是內(nèi)部標(biāo)識符,因?yàn)樗鼈冊趯?shí)現(xiàn)世界有真實(shí)的意義,屬于合法的屬性。

(2)操作與方法

操作是一個函數(shù)或過程,比如,open和close都是Windows類的操作,類中所有的對象都共享相同的操作,因此將對象能夠做什么的行為稱為操作,通常將相同的操作應(yīng)用于許多不同的類稱為多態(tài)。

方法是對操作的實(shí)現(xiàn),其表現(xiàn)為OOP某個類的成員函數(shù)。比如,類Validator有一個操作validate,其校驗(yàn)過程是通過validate調(diào)用不同的函數(shù)實(shí)現(xiàn)的。比如,范圍值校驗(yàn)和奇偶校驗(yàn)。雖然這些方法在邏輯上都執(zhí)行相同的任務(wù)——數(shù)據(jù)校驗(yàn),但是每種方法的實(shí)現(xiàn)代碼會有所不同。

如圖 4.2所示RangeValidator類有min和max屬性,以及validate操作,min、max和validate都是RangeValidator的特征。特征是描述屬性或操作的類屬詞匯,類似地OddEvenValidator有isEven屬性和validate操作。

圖 4.2 操作的UML表示法

注意,validate()省略了括號中的輸入?yún)?shù),即“validate(pThis:void *, value:int):bool”。validate的一個參數(shù)是pThis,其類型是void *;它的另一個參數(shù)value,其類型是int。當(dāng)一項(xiàng)操作在幾個類上都有方法時,這些方法都要有相同的簽名,即相同的參數(shù)數(shù)量和類型,以及返回值的類型。

UML的方框表示類,最多有三格,從上到下每個格里分別包含了類名、屬性列表和操作列表。類方框中的屬性和操作的框格可以選擇顯示或隱藏,缺少屬性說明沒有指定屬性,缺少操作框說明沒有指定操作。相反,空框格意味著屬性是指定的,只是沒有顯示屬性而已。

操作列表約定用常規(guī)字體列出操作名,左對齊,首字母小寫。比如,參數(shù)列表和操作結(jié)果的類型,用括號將參數(shù)列表括起來,并用逗號分隔參數(shù)。結(jié)果類型之前有一個冒號,除非括號中空的參數(shù)列表明確表示沒有參數(shù),否則就不能下結(jié)論。

(3)客戶和服務(wù)器模式

在OOP中,如果一個類公開了一些方法供其它類調(diào)用,那么這個類被稱為服務(wù)器,公開的這些方法被稱為服務(wù),而調(diào)用這些服務(wù)的類就是客戶。理論上客戶類調(diào)用服務(wù)器類的服務(wù),即客戶向服務(wù)器發(fā)送了一條消息。而客戶和服務(wù)器的概念是相對而言的,當(dāng)A類向B類提供了功能接口時,則類A是服務(wù)器,B類是客戶;如果類B也同時為類A提供了功能接口,則類B是服務(wù)器,類A是客戶。

設(shè)計(jì)良好的服務(wù)器應(yīng)該將其實(shí)現(xiàn)細(xì)節(jié)隱藏起來,客戶僅需知道服務(wù)器提供的接口即可。接口就是客戶所能調(diào)用的那些函數(shù),這些函數(shù)將消息發(fā)給服務(wù)器,那么服務(wù)器就知道客戶需要什么樣的服務(wù),服務(wù)器會返回一些數(shù)據(jù)給客戶,或執(zhí)行客戶所需的任務(wù)等。

(4)消息傳遞和方法調(diào)用

在OOP中,類和對象表現(xiàn)為服務(wù)器,使用類和對象的模塊表現(xiàn)為客戶。客戶通過特殊的方式請求服務(wù)。那么到底如何讓對象為我們做有用的事情呢?必須有一種方法能向?qū)ο笞龀稣埱螅沟盟茏瞿臣虑椋热纾瓿山灰住⒃谄聊簧袭媹D或打開開關(guān)。可以向?qū)ο蟀l(fā)出的請求是由它的接口定義的,而接口是由類型定義的。

雖然接口規(guī)定了我們能向特定的對象發(fā)出什么請求,但必須有代碼滿足這種請求,再加上隱藏的數(shù)據(jù)就組成了實(shí)現(xiàn)。類型對每個可能的請求都有一個相關(guān)的函數(shù),當(dāng)向?qū)ο蟀l(fā)出請求時,就調(diào)用這個函數(shù)。這個過程被概括為向?qū)ο蟆鞍l(fā)送消息”(提出請求),對象根據(jù)這個消息確定做什么(執(zhí)行代碼)。

對象之間的邏輯接口通過消息傳遞實(shí)現(xiàn),消息是對對象之間通信的的抽象。常見的消息傳遞方法是直接調(diào)用定義于接收方對象中的操作,比如,當(dāng)對象A調(diào)用對象B的一個方法時,對象A就是在向?qū)ο驜發(fā)送一個消息,對象B的響應(yīng)由其返回值定義,但只有對象的公共方法才能由另一個對象調(diào)用。

使用消息傳遞可以實(shí)現(xiàn)松耦合,特別在分析階段,不用指定接口的細(xì)節(jié),比如,同步、函數(shù)調(diào)用格式和超時等。當(dāng)全面理解了所有的問題后,接下來就可以決定設(shè)計(jì)和實(shí)現(xiàn)的細(xì)節(jié)了。通常對象接口可以看成對象與外部世界之間制定的契約,契約是由一組協(xié)議定義的,對象參與到這些協(xié)議中。接口協(xié)議包括前置條件、后置條件和不變量。

前置條件是當(dāng)該操作被調(diào)用時,必須成立的條件。即在調(diào)用之前應(yīng)該校驗(yàn)傳入?yún)?shù)是否正確,只有正確才能執(zhí)行該方法。也就是說,必須在消息發(fā)送或接收之前保證為真的條件,這是消息發(fā)送者的職責(zé)。一旦通過前置條件的校驗(yàn)方法必須執(zhí)行,且必須保證執(zhí)行結(jié)果符合契約,這就是后置條件。也就是說,后置條件是當(dāng)該操作完成時,必須成立的條件。即在處理消息時必須保證為真,這是消息接收者的職責(zé)。不變量是指在任何時刻都必須成立的條件,包括操作執(zhí)行前、執(zhí)行時和執(zhí)行后。

(5)屬性抽象與行為抽象

OO程序設(shè)計(jì)思想可以采用抽象的方法,對現(xiàn)實(shí)世界中的多個具體對象進(jìn)行概括分析,得到這類對象所具有的共同屬性和行為,加以描述就形成了類。雖然都是同一個類的對象,但每個對象的屬性不同,于是就形成了不同的具體對象實(shí)體。

抽象一般分為屬性抽象和行為抽象兩種,屬性抽象是尋找一類對象共有的屬性,比如,在范圍值校驗(yàn)器RangeValidator類中,使用整型變量min和max來描述push到棧中的數(shù)值范圍,然后將min和max變量作為類的成員變量描述對象的屬性,即“屬性是包含在對象中的變量”。而行為抽象則是尋找這類對象所具有的共同行為特征,比如,對push到棧中的值進(jìn)行范圍值校驗(yàn),同樣,也可以為這個類添加相應(yīng)的函數(shù),最終將該函數(shù)作為類的成員函數(shù)描述對象的行為,即“方法是包含在對象中的函數(shù)”。

在面向過程的編程中,程序是由模塊組成的,一個模塊就是一個過程,通常采用自頂而下的設(shè)計(jì)方法。而面向?qū)ο蟮木幊膛c設(shè)計(jì)著眼于解決面向過程的編程和自頂而下設(shè)計(jì)中出現(xiàn)的一些問題,由于在面向?qū)ο蟮木幊讨袠?gòu)成模塊的基本單元是類,而不是過程,因此面向?qū)ο笤O(shè)計(jì)是面向?qū)ο缶幊痰脑O(shè)計(jì)方法,它著重于類的設(shè)計(jì),通過類的設(shè)計(jì)完成對實(shí)體的建模任務(wù),類建模的目的是描述對象。

在面向過程的編程中,描述一個物體時,數(shù)據(jù)和方法是分開的。比如,當(dāng)通過網(wǎng)絡(luò)發(fā)送信息時,則只會發(fā)送相關(guān)的數(shù)據(jù),并認(rèn)為網(wǎng)絡(luò)另一端的程序知道如何進(jìn)行處理。也就是說,如果兩者之間沒有握手協(xié)議,則網(wǎng)絡(luò)另一端的程序不知道如何處理。而對象可以定義為“同時包含”數(shù)據(jù)和行為的一個實(shí)例,即通過封裝機(jī)制將數(shù)據(jù)和行為捆綁在一起,形成一個完整的、具有屬性和行為的對象。比如,當(dāng)通過網(wǎng)絡(luò)傳送對象時,則傳送的是整個對象。因此使用OO技術(shù)的程序?qū)嶋H上就是多個對象的集合,這里的“同時包含”正是OO程序設(shè)計(jì)與面向過程程序設(shè)計(jì)方法的重要區(qū)別。

由此可見,以后在分析新的對象時,都要從屬性和行為兩個方面進(jìn)行抽象和概括,提取對象的共同特征,而整個抽象過程是一個從具體到一般的過程。如果說抽象是將很多對象的共有特征提取出來成為類的成員屬性和成員函數(shù),那么封裝機(jī)制則是將這些特征進(jìn)行有機(jī)地結(jié)合形成一個完整的類。

>>>4.2.3 封裝

類和對象既是獨(dú)立的概念,又密切相關(guān)。每個對象都是某個類的一個實(shí)例,每個類都有0或多個實(shí)例。對于所有的應(yīng)用來說,類幾乎都是靜態(tài)的。這就意味著,對象一旦被創(chuàng)建,它的類就確定了。

雖然最具挑戰(zhàn)的是如何確定類和對象,但只要正確使用面向?qū)ο蠓治觯∣gject Oriented

Analysis,OOA)和面向?qū)ο笤O(shè)計(jì)(Object Oriented Design,OOD)就能得到具有價值的領(lǐng)域模型和設(shè)計(jì)模型。OOA、OOD與OOP到底是什么關(guān)系?OOA的結(jié)果可以作為OOD開始的模型,OOD的結(jié)果可以作為藍(lán)圖,利用OOP方法實(shí)現(xiàn)一個系統(tǒng)。

在OOA和OOD中,不需要考慮特定的語言機(jī)制,“關(guān)鍵是尋找并解決業(yè)務(wù)問題,完成概念分析和設(shè)計(jì)。在OOA和OOD的早期,開發(fā)者的主要任務(wù)有兩項(xiàng):

  • 從需求的詞匯表中確定類;

  • 創(chuàng)建一些結(jié)構(gòu),讓多組對象一起工作,提供滿足需求的行為。

通常我們將這樣的類和對象統(tǒng)稱為問題域的關(guān)鍵抽象,即關(guān)鍵抽象反映了問題域的詞匯表,可以從問題域中發(fā)現(xiàn),也可以作為設(shè)計(jì)的一部分發(fā)明;將這些協(xié)作結(jié)構(gòu)稱為實(shí)現(xiàn)的機(jī)制,其考慮的是許多不同類型的對象之間的協(xié)作活動。

確定關(guān)鍵抽象包括兩個過程:發(fā)現(xiàn)和發(fā)明,通過與領(lǐng)域?qū)<遥ㄓ脩簦┙涣鳎瑢l(fā)現(xiàn)領(lǐng)域?qū)<宜褂玫某橄蟆H绻I(lǐng)域?qū)<姨峒八敲催@個抽象通常是很重要的,比如,范圍值校驗(yàn)器RangeValidator。而發(fā)明就是創(chuàng)造新的類和對象的過程,雖然它們不一定是問題域的組成部分,但在設(shè)計(jì)或?qū)崿F(xiàn)中也是很重要的。比如,微型數(shù)據(jù)庫、鏈表、棧、隊(duì)列等。這些關(guān)鍵抽象是具體設(shè)計(jì)的結(jié)果,不屬于問題域。因此在設(shè)計(jì)過程中,開發(fā)者不僅需要考慮單個類的設(shè)計(jì),還要考慮這些類的實(shí)例如何一起工作,并使用場景驅(qū)動分析過程。由此可見,關(guān)鍵抽象反映了業(yè)務(wù)領(lǐng)域的抽象,機(jī)制是設(shè)計(jì)的靈魂。

假設(shè)希望對push到棧中的值,既可以進(jìn)行范圍值校驗(yàn),也可以進(jìn)行偶校驗(yàn)。從面向?qū)ο蟮慕嵌葋砜矗紫纫獜膯栴}的描述中發(fā)現(xiàn)對象,當(dāng)找到對象后,接著開始通過共性和差異性分析這些對象所具有的屬性和行為,然后利用面向?qū)ο蟮姆庋b機(jī)制將其封裝成類。

根據(jù)問題的描述,范圍值校驗(yàn)器就是一個RangeValidator具體類,其屬性是范圍值校驗(yàn)參數(shù)min和max,其行為就是將符合范圍要求的數(shù)值push到棧中。因此只要將RangeValidator的屬性和行為作為成員封裝到結(jié)構(gòu)體中,就形成了RangeValidator類,這是面向過程編程的C程序員最容易想到,也最容易理解的方法。

為了支持這種風(fēng)格,C允許將方法作為某個結(jié)構(gòu)體的一部分來聲明,那么操作存儲在結(jié)構(gòu)體中的數(shù)據(jù)就很容易了,詳見程序清單 4.1。

程序清單 4.1 范圍值校驗(yàn)器類接口

其中,類名字的首字母為大寫,對象名字的首字母為小寫。由此可見,通過擴(kuò)展已有結(jié)構(gòu)體的概念創(chuàng)造了一個全新的概念——類,類如同種類一樣,定義一個類就是在創(chuàng)造一個新的數(shù)據(jù)類型。雖然聲明一個類的變量如同聲明一個結(jié)構(gòu)體的變量一樣,但聲明一個類的變量被稱為對象,因此有了類即可聲明一個RangeValidator類的對象rangeValidator。通常也稱rangeValidator對象是RangeValidator類的一個實(shí)例,就是創(chuàng)建類的一個實(shí)例的過程。

在進(jìn)行范圍值校驗(yàn)時,首先需要判斷value值是否符合要求?validateRange()函數(shù)接口的實(shí)現(xiàn)詳見程序清單 4.2。

程序清單 4.2 范圍值校驗(yàn)器接口函數(shù)的實(shí)現(xiàn)

偶校驗(yàn)器OddEvenValidator具體類和對象oddEvenValidator的定義詳見程序清單 4.3。

程序清單 4.3 偶校驗(yàn)器類接口

在進(jìn)行偶校驗(yàn)時,同樣需要判斷value值是否符合要求?validateOddEven()函數(shù)接口的實(shí)現(xiàn)詳見程序清單 4.4。

程序清單 4.4 偶校驗(yàn)器接口函數(shù)的實(shí)現(xiàn)

顯然,無論是什么校驗(yàn)器,其共性是value值合法性判斷,因此可以共用一個函數(shù)指針,即特殊的函數(shù)指針類型RangeValidate和OddEvenValidate被泛化成了一般的函數(shù)指針類型Validate。其次,由于每個函數(shù)都有一個指向當(dāng)前對象的pThis指針,因此特殊的結(jié)構(gòu)體類型RangeValidator *和OddEvenValidator *被泛化成了void *類型,即可接受任何類型的數(shù)據(jù):

校驗(yàn)器泛化接口的實(shí)現(xiàn)詳見程序清單 4.5。

程序清單 4.5 通用校驗(yàn)器接口的實(shí)現(xiàn)(validator.c)

為了便于閱讀,程序清單 4.6展示了范圍值校驗(yàn)器和奇偶校驗(yàn)器的接口。

程序清單 4.6 通用校驗(yàn)器接口(validator.h)

這個接口主要由所有的操作聲明構(gòu)成,這些操作適用于這個類的所有對象,詳見圖 4.3。

圖 4.3 類圖

以范圍值校驗(yàn)器為例,假設(shè)min=0,max=9,使用名為newRangeValidator的宏將結(jié)構(gòu)體初始化的使用方法如下:

注意,RangeValidator類是在編譯時定義的,而rangeValidator對象是在運(yùn)行時作為類的實(shí)例創(chuàng)建的。宏展開后如下:

其相當(dāng)于:

如果有以下定義:

即可通過pValidator引用RangeValidator的min和max。校驗(yàn)函數(shù)的調(diào)用方式如下:

以上調(diào)用形式的前提是已知pValidator指向了確定的結(jié)構(gòu)體類型,如果pValidator將指向未知的校驗(yàn)器,顯然以上調(diào)用形式無法做到通用,那么如何調(diào)用?

雖然pValidator與&rangeValidator.validate的類型不一樣,但它們的值相等,因此可以利用這一特性獲取validateRange()函數(shù)的地址。即:

其調(diào)用形式如下:

根據(jù)OCP開閉原則,由于不允許修改push()函數(shù),因此需要編寫一個通用的擴(kuò)展push功能的pushWithValidate()函數(shù),詳見程序清單 4.7。

程序清單 4.7 pushWithValidate()

其中,stack是指向當(dāng)前對象(棧)的指針,用于請求對象對自身執(zhí)行某些操作,而結(jié)構(gòu)體的成員變量就是通過stack指針找到自己所屬的對象的。pValidator為指向校驗(yàn)器的指針,如果無需校驗(yàn),則將pValidator置NULL并返回true。

使用validator.h接口的通用校驗(yàn)器范例程序詳見程序清單 4.8。

程序清單 4.8 通用校驗(yàn)器使用范例程序

由此可見,雖然在結(jié)構(gòu)體內(nèi)置函數(shù)指針也可以創(chuàng)建類,但其中的每個類都是一個獨(dú)立的單元,每個都要從頭開始。且不同類之間沒有任何關(guān)系,因?yàn)槊總€類的開發(fā)者都根據(jù)自己的選擇提供方法。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 對象
    +關(guān)注

    關(guān)注

    1

    文章

    38

    瀏覽量

    17380

原文標(biāo)題:周立功:類與對象的應(yīng)用

文章出處:【微信號:ZLG_zhiyuan,微信公眾號:ZLG致遠(yuǎn)電子】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    Python的面向對象編程詳解

    一般編程可分為面向過程編程,和面向對象編程。Python的
    發(fā)表于 09-04 16:35 ?526次閱讀
    Python的<b class='flag-5'>面向</b><b class='flag-5'>對象</b><b class='flag-5'>編程</b>詳解

    labview面向對象編程

    點(diǎn)擊學(xué)習(xí)>>《龍哥手把手教你學(xué)LabVIEW視覺設(shè)計(jì)》視頻教程使用LabVIEW面向對象編程方法,對于大型測試應(yīng)用程序來講,面向對象相對于
    發(fā)表于 11-24 11:01

    LabVIEW面向對象編程入門介紹

    LabVIEW面向對象編程入門介紹庫描述介紹
    發(fā)表于 11-20 10:51

    LabVIEW面向對象的ActorFramework(1)

    ` 本帖最后由 bollworm 于 2020-2-10 14:54 編輯 本系列文章主要闡述以下幾個問題:(1)什么是面向對象編程?(2)為什么要學(xué)習(xí)面向
    發(fā)表于 02-10 14:09

    如何用C語言實(shí)現(xiàn)面向對象編程

    、組合、多態(tài)等面向對象的功能,但C語言有struct和函數(shù)指針。我們可以用struct中的數(shù)據(jù)和函數(shù)指針,以此來模擬對象的行為。所以在正式開始設(shè)計(jì)模式前,先看看如何用C語言實(shí)現(xiàn)
    發(fā)表于 07-12 07:24

    面向對象編程及其三大特性 精選資料分享

    Oriented)是一種以過程為中心的編程思想。這些都是以什么正在發(fā)生為 目標(biāo)進(jìn)行編程,不同于面向對象的是誰在受影響。與面向
    發(fā)表于 07-21 08:38

    談?wù)?b class='flag-5'>面向對象編程

    工業(yè)控制系統(tǒng)的PLC程序中也可以采用這種設(shè)計(jì)思想,雖然我們無法實(shí)現(xiàn)面向對象的很多優(yōu)秀特點(diǎn)如“繼承”,甚至于它根本就不具備面向對象編程語言的特
    發(fā)表于 09-08 07:47

    面向對象編程語言的特點(diǎn)

    工業(yè)控制系統(tǒng)的PLC程序中也可以采用這種設(shè)計(jì)思想,雖然我們無法實(shí)現(xiàn)面向對象的很多優(yōu)秀特點(diǎn)如“繼承”,甚至于它根本就不具備面向對象編程語言的特
    發(fā)表于 09-08 07:44

    面向對象編程的基本概念及其特點(diǎn)

    ,但面向對象編程的基本概念就是的實(shí)例(即對象),我們只需要使用這種概念就可以了。在計(jì)算機(jī)編
    發(fā)表于 09-09 06:33

    面向對象編程介紹

    目錄一、面向對象編程介紹1.面向過程編程2.函數(shù)式編程3.
    發(fā)表于 12-13 07:22

    面向對象編程練習(xí)

    實(shí)驗(yàn) 3 面向對象編程練習(xí) 一、實(shí)驗(yàn)?zāi)康?    通過編程和上機(jī)實(shí)驗(yàn)理解 Java 語言是如何體現(xiàn)面向
    發(fā)表于 09-23 18:57 ?3037次閱讀

    plc面向對象編程架構(gòu)與實(shí)現(xiàn)

    面向對象編程是計(jì)算機(jī)高級語言的一種先進(jìn)的編程模式,在工業(yè)控制系統(tǒng)的PLC程序中也可以采用這種設(shè)計(jì)思想,雖然我們無法實(shí)現(xiàn)面向
    發(fā)表于 01-31 15:00 ?4238次閱讀
    plc<b class='flag-5'>面向</b><b class='flag-5'>對象</b><b class='flag-5'>編程</b>架構(gòu)與實(shí)現(xiàn)

    Labview面向對象編程快速入門教程

    面向對象編程中, 用來表示通用特性。 例如,假設(shè)有一個描述汽車的中定義了各種汽車的通
    發(fā)表于 07-31 08:00 ?82次下載
    Labview<b class='flag-5'>面向</b><b class='flag-5'>對象</b><b class='flag-5'>編程</b>快速入門教程

    西門子PLC面向對象編程

    ,但面向對象編程的基本概念是 的實(shí)例(即對象),我們只需要使用這個概念。在計(jì)算機(jī)
    發(fā)表于 04-17 11:41 ?7次下載
    西門子PLC<b class='flag-5'>面向</b><b class='flag-5'>對象</b><b class='flag-5'>編程</b>

    Python中的對象詳解

    Python 是一種面向對象編程語言,它支持對象是一種用戶自定義的數(shù)據(jù)類型,用于定義
    的頭像 發(fā)表于 04-20 16:53 ?1067次閱讀