楊韜
(廣州致遠(yuǎn)電子股份有限公司,廣東 廣州 510660)
摘要:多年以來(lái),C語(yǔ)言在嵌入式軟件開(kāi)發(fā)中被廣泛使用,但由于開(kāi)發(fā)人員和應(yīng)用場(chǎng)景等原因,面向?qū)ο?/a>、設(shè)計(jì)模式等優(yōu)秀的軟件開(kāi)發(fā)方法始終沒(méi)有很好地運(yùn)用起來(lái)。時(shí)至今日,物聯(lián)網(wǎng)等應(yīng)用的興起,給嵌入式軟件開(kāi)發(fā)帶來(lái)新的挑戰(zhàn),而傳統(tǒng)的面向過(guò)程開(kāi)發(fā)已經(jīng)難以支撐這些復(fù)雜的應(yīng)用。因此,有必要在嵌入式軟件開(kāi)發(fā)中引入面向?qū)ο?、設(shè)計(jì)模式等優(yōu)秀的軟件開(kāi)發(fā)方法。面向?qū)ο笫乾F(xiàn)代軟件方法的根基,面向?qū)ο篌w現(xiàn)在類上,而封裝為類的第一大特性。文章以類的封裝特性為切入點(diǎn),結(jié)合C語(yǔ)言的特性,討論了C語(yǔ)言實(shí)現(xiàn)類封裝的方法,并給出了實(shí)例。
關(guān)鍵詞:C語(yǔ)言;面向?qū)ο?;類;封裝
0引言
物聯(lián)網(wǎng)等應(yīng)用的興起,給嵌入式軟件開(kāi)發(fā)帶來(lái)新的挑戰(zhàn),而傳統(tǒng)的面向過(guò)程開(kāi)發(fā)已經(jīng)難以支撐這些復(fù)雜的應(yīng)用。因此,有必要在嵌入式軟件開(kāi)發(fā)中引入面向?qū)ο蟆⒃O(shè)計(jì)模式等優(yōu)秀的軟件開(kāi)發(fā)方法。本文首先介紹了面向?qū)ο蟊匾幕靖拍?,然后引入了UML類圖,通過(guò)使用C語(yǔ)言來(lái)實(shí)現(xiàn)一個(gè)Human類,討論了如何使用C語(yǔ)言來(lái)實(shí)現(xiàn)類的封裝特性,并給出了對(duì)應(yīng)的分析。
1基本概念
1.1對(duì)象[1]
對(duì)象是人們要進(jìn)行研究的任何事物,從最簡(jiǎn)單的整數(shù)到復(fù)雜的飛機(jī)等均可看作對(duì)象,它不僅能表示具體的事物,還能表示抽象的規(guī)則、計(jì)劃或事件。
對(duì)象具有狀態(tài),一般用數(shù)據(jù)值來(lái)描述它的狀態(tài)。
對(duì)象還有操作,用于改變對(duì)象的狀態(tài),對(duì)象及其操作就是對(duì)象的行為。
對(duì)象實(shí)現(xiàn)了數(shù)據(jù)和操作的結(jié)合,使數(shù)據(jù)和操作封裝于對(duì)象的統(tǒng)一體中。
1.2面向?qū)ο?/strong>
簡(jiǎn)而言之,面向?qū)ο缶褪前芽陀^存在或主觀抽象的事物(即對(duì)象)抽象成類。
所謂抽象就是去異求同,從眾多的事物(即對(duì)象)中抽取出共同的、本質(zhì)性的特征,舍棄其非本質(zhì)的特征。比如香蕉、蘋(píng)果、哈密瓜等,它們共同的特性就是水果。得出水果概念的過(guò)程就是一個(gè)抽象的過(guò)程。在抽象時(shí),同與不同,取決于從什么角度上來(lái)抽象。抽象的角度取決于分析問(wèn)題的目的。
具有相同特性(數(shù)據(jù)元素)和行為(功能)的對(duì)象的抽象就是類。因此,對(duì)象的抽象是類,類的具體化就是對(duì)象,也可以說(shuō)類的實(shí)例是對(duì)象。
1.3類
面向?qū)ο笥腥筇匦裕悍庋b、繼承、多態(tài),這些特性主要通過(guò)類來(lái)體現(xiàn)。類就是一個(gè)封裝了屬性以及相關(guān)操作的代碼的邏輯實(shí)體。
類具有屬性,它是對(duì)象的狀態(tài)的抽象,用數(shù)據(jù)結(jié)構(gòu)來(lái)描述類的屬性。
類具有方法,它是對(duì)象的行為的抽象,用方法名和實(shí)現(xiàn)該操作的方法來(lái)描述。
除了封裝屬性和操作外,類還具有訪問(wèn)控制的功能,比如,某些屬性和方法可以是私有的,不能被外界訪問(wèn),通過(guò)訪問(wèn)控制,能夠?qū)?nèi)部數(shù)據(jù)提供不同級(jí)別的保護(hù),以防止外界意外地改變或使用了私有部分。不同的編程語(yǔ)言提供的訪問(wèn)控制等級(jí)不盡相同,但都有公有、私有兩個(gè)等級(jí)。
類是抽象的數(shù)據(jù)類型,在內(nèi)存中并不存在(Python等動(dòng)態(tài)語(yǔ)言除外),只有類的實(shí)例存在于內(nèi)存中。
2UML類圖
在面向?qū)ο笤O(shè)計(jì)開(kāi)發(fā)中,通常使用UML工具來(lái)進(jìn)行分析設(shè)計(jì)。比如,可以使用UML類圖來(lái)描述類。
UML類圖很簡(jiǎn)單,用一個(gè)矩形框代表一個(gè)類,矩形框內(nèi)部被隔為三部分:上面部分為類的名字,中間部分為類的屬性,下面部分為類的方法。對(duì)于屬性和方法,還可以使用“+”、“-”修飾符來(lái)表示訪問(wèn)權(quán)限,“+”為公有屬性、“-”為私有屬性。
如圖1所示,該類圖描述了一個(gè)名為“Human”的類?!癏uman”類抽象并封裝了“人”;屬性“name”是對(duì)人姓名的抽象,因?yàn)槿说男彰枪_(kāi)的,所以被設(shè)置為公有屬性;屬性“money”是對(duì)人所擁有的財(cái)富的抽象,因?yàn)槊總€(gè)人的財(cái)富都不是公開(kāi)的,所以被設(shè)置為私有屬性;方法“buy”是對(duì)購(gòu)物這一行為的抽象,方法“talk”是對(duì)講話這一行為的抽象,這兩個(gè)方法都是社會(huì)活動(dòng),所以被設(shè)置為公有屬性。
設(shè)計(jì)類的過(guò)程就是抽象的過(guò)程,抽象的結(jié)果取決于抽象時(shí)所站的角度,比如,如果是警察來(lái)抽象“Human”,他可能會(huì)添加一個(gè)“isBadGuy”屬性。
UML類圖主要用于輔助分析和設(shè)計(jì)階段,在設(shè)計(jì)類時(shí)應(yīng)聚焦在與當(dāng)前問(wèn)題有關(guān)的重要屬性和行為,無(wú)關(guān)的屬性和方法統(tǒng)統(tǒng)去掉,確保UML類圖是簡(jiǎn)潔有效的。除非私有屬性或方法會(huì)影響到問(wèn)題的理解或者類的實(shí)現(xiàn),否則UML類圖中不要出現(xiàn)私有屬性和方法,私有屬性通常在實(shí)現(xiàn)階段才會(huì)去考慮。
UML類圖以及其他UML元素都是輔助軟件開(kāi)發(fā)的工具,使用UML進(jìn)行設(shè)計(jì)時(shí),只要相關(guān)人員能夠通過(guò)UML圖看懂你的設(shè)計(jì)、不妨礙溝通就可以了,即使用草稿紙來(lái)作圖也是可以的,所以,不用太過(guò)糾結(jié)那些細(xì)節(jié),且一定要避免過(guò)度設(shè)計(jì)。
3C語(yǔ)言的類封裝實(shí)現(xiàn)
很多現(xiàn)代編程語(yǔ)言都有原生的面向?qū)ο笾С?,比如C++、JAVA、Python等,這些編程語(yǔ)言提供了class數(shù)據(jù)類型,在這些編程語(yǔ)言中類實(shí)際上就是一種數(shù)據(jù)類型,因此能夠更好地支持面向?qū)ο缶幊獭?/p>
實(shí)際上,面向?qū)ο笫桥c編程語(yǔ)言無(wú)關(guān)的,更像是一種思想,且不局限于軟件開(kāi)發(fā)活動(dòng),任何需要分析解決問(wèn)題的場(chǎng)合都可以使用面向?qū)ο蟆?/p>
C語(yǔ)言并沒(méi)有類的概念,但是可以從類的特性出發(fā),利用C語(yǔ)言的某些特性來(lái)實(shí)現(xiàn)類的用法。關(guān)于類,首先要解決的就是封裝問(wèn)題,類的封裝特性需要能夠封裝屬性和方法,還要有訪問(wèn)控制??梢允褂?h、.c文件和結(jié)構(gòu)體來(lái)完成封裝。
下面以圖1中Human類的C語(yǔ)言實(shí)現(xiàn)為例來(lái)敘述C語(yǔ)言的類封裝問(wèn)題,本文使用human.h、human.c、struct human三個(gè)元素來(lái)完成封裝,human.c為human.h中函數(shù)聲明的實(shí)現(xiàn),本文不討論這些細(xì)節(jié),所以只給出human.h的關(guān)鍵代碼片段,如下所示:
typedef struct human {
const char *name;
int _money;
} human_t;
human_t *human_init(human_t *p_this, const char *name, intmoney);
voidhuman_talk(human_t*p_this, const char*p_words);
voidhuman_buy(human_t*p_this, const char *p_something, unsignedprice, unsignedcount);
voidhuman_deinit(human_t *p_this);
(1)類名
Human類的名稱體現(xiàn)在human.c、human.h以及human.h中所有全局符號(hào)的命名上,這些命名全部使用關(guān)鍵字human作為前綴。
(2)屬性
Human類的屬性體現(xiàn)在自定義類型human_t中,human_t實(shí)際上為結(jié)構(gòu)體struct human,它有兩個(gè)成員:name和_money,分別對(duì)應(yīng)類圖中的屬性+name和-money,特別留意_money成員前的“_”,這是為了警示類的使用者“此成員為私有屬性,不可使用”。
(3)方法
Human類的方法體現(xiàn)在human_talk()、human_buy()這兩個(gè)函數(shù)上,分別對(duì)應(yīng)類圖中的方法+buy()和+talk()。此外,還可以注意到有human_init()、human_deinit()這兩個(gè)函數(shù),分別為Human類的構(gòu)造、析構(gòu)方法。構(gòu)造、析構(gòu)方法分別用于類對(duì)象的初始化和解初始化。
構(gòu)造函數(shù)human_init()需要用戶提供Human對(duì)象的內(nèi)存,通過(guò)第一個(gè)參數(shù)p_this傳遞,對(duì)象的內(nèi)存等價(jià)于一個(gè)human_t變量。
C語(yǔ)言中可以使用C文件中的static函數(shù)實(shí)現(xiàn)私有方法,假如Human類有私有方法money_pay(),則其C語(yǔ)言實(shí)現(xiàn)如下:
// human.c
static int __human_money_pay (human_t *p_this, unsignedcost)
{ … }
UML類圖中一般不會(huì)顯式地出現(xiàn)構(gòu)造、析構(gòu)和私有這三種方法,除非需要在類的構(gòu)造、析構(gòu)和實(shí)現(xiàn)上有特殊說(shuō)明。
另外需要注意的是,這幾個(gè)方法函數(shù)的第一個(gè)參數(shù)都是human_t *類型,且名稱為p_this,這是C語(yǔ)言面向?qū)ο缶幊膛c面向過(guò)程的最大不同:p_this為指向類實(shí)例(即對(duì)象)的指針,所有的方法操作都需要“針對(duì)”一個(gè)對(duì)象,p_this指針由類的構(gòu)造函數(shù)返回,比如,human_init()構(gòu)造一個(gè)Human實(shí)例,然后返回指向此實(shí)例的p_this指針,然后就可以調(diào)用human_talk(p_this, …)等方法對(duì)實(shí)例進(jìn)行操作。
(4)訪問(wèn)控制
在Human類的C語(yǔ)言實(shí)現(xiàn)中,屬性被定義為human_t中的兩個(gè)成員,而 human_t被定義在用戶可見(jiàn)的human.h中,所以human_t是暴露給用戶的,因此,從語(yǔ)法上講,Human類的兩個(gè)屬性是暴露給用戶的,即都是公有屬性。雖然語(yǔ)法上不能支持私有,但可以在編程規(guī)范上設(shè)定“私有屬性以短下劃線“_”開(kāi)頭”,比如“_money”,如此從某種意義上實(shí)現(xiàn)了屬性的訪問(wèn)控制。
在Human類的C語(yǔ)言實(shí)現(xiàn)中,方法被定義為human.c中的函數(shù)。公共方法對(duì)應(yīng)的函數(shù)都沒(méi)有“static”關(guān)鍵字,且在human.h中有對(duì)應(yīng)的函數(shù)聲明。而私有方法對(duì)應(yīng)的函數(shù)都有“static”關(guān)鍵字,這些私有方法只能在human.c文件內(nèi)部調(diào)用,對(duì)用戶不可見(jiàn)。由此可知,C語(yǔ)言本身就能支持方法的訪問(wèn)控制。
4結(jié)論
本文通過(guò)使用C語(yǔ)言實(shí)現(xiàn)一個(gè)Human類,討論了如何使用C語(yǔ)言來(lái)實(shí)現(xiàn)類的封裝特性。在C++等面向?qū)ο笳Z(yǔ)言中,使用class對(duì)類做了原生的支持,使用起來(lái)非常簡(jiǎn)單。盡管C語(yǔ)言并不是原生支持類,但通過(guò)語(yǔ)言、概念、規(guī)范上的處理,也能實(shí)現(xiàn)類的封裝特性。用C語(yǔ)言實(shí)現(xiàn)類的封裝相當(dāng)于解決了C面向?qū)ο蟮年P(guān)鍵第一步,在其基礎(chǔ)之上可以引入更多現(xiàn)代軟件方法。
參考文獻(xiàn)
?。?] 百度. 百度百科/面向?qū)ο螅跡B/OL].[2016-08-08].http://baike.baidu.com/link?url=6XlXEOSlrKn87S7SJv4UW SX7EjstoDVm wJ13OAod XUrUrnZkVg3ntPFir Ey5c6mqObZZ OevQI6K3Ungq1Mq.