楊韜
?。◤V州致遠(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ū)ο蟆⒃O(shè)計(jì)模式等優(yōu)秀的軟件開(kāi)發(fā)方法,。面向?qū)ο笫乾F(xiàn)代軟件方法的根基,,面向?qū)ο篌w現(xiàn)在類(lèi)上,而封裝為類(lèi)的第一大特性,。文章以類(lèi)的封裝特性為切入點(diǎn),,結(jié)合C語(yǔ)言的特性,討論了C語(yǔ)言實(shí)現(xiàn)類(lèi)封裝的方法,并給出了實(shí)例,。
關(guān)鍵詞:C語(yǔ)言,;面向?qū)ο螅活?lèi),;封裝
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類(lèi)圖,通過(guò)使用C語(yǔ)言來(lái)實(shí)現(xiàn)一個(gè)Human類(lèi),,討論了如何使用C語(yǔ)言來(lái)實(shí)現(xiàn)類(lèi)的封裝特性,,并給出了對(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ì)象)抽象成類(lèi),。
所謂抽象就是去異求同,從眾多的事物(即對(duì)象)中抽取出共同的,、本質(zhì)性的特征,,舍棄其非本質(zhì)的特征。比如香蕉,、蘋(píng)果,、哈密瓜等,它們共同的特性就是水果,。得出水果概念的過(guò)程就是一個(gè)抽象的過(guò)程,。在抽象時(shí),,同與不同,取決于從什么角度上來(lái)抽象,。抽象的角度取決于分析問(wèn)題的目的,。
具有相同特性(數(shù)據(jù)元素)和行為(功能)的對(duì)象的抽象就是類(lèi)。因此,,對(duì)象的抽象是類(lèi),,類(lèi)的具體化就是對(duì)象,也可以說(shuō)類(lèi)的實(shí)例是對(duì)象,。
1.3類(lèi)
面向?qū)ο笥腥筇匦裕悍庋b,、繼承、多態(tài),,這些特性主要通過(guò)類(lèi)來(lái)體現(xiàn),。類(lèi)就是一個(gè)封裝了屬性以及相關(guān)操作的代碼的邏輯實(shí)體。
類(lèi)具有屬性,,它是對(duì)象的狀態(tài)的抽象,,用數(shù)據(jù)結(jié)構(gòu)來(lái)描述類(lèi)的屬性。
類(lèi)具有方法,,它是對(duì)象的行為的抽象,,用方法名和實(shí)現(xiàn)該操作的方法來(lái)描述。
除了封裝屬性和操作外,,類(lèi)還具有訪問(wèn)控制的功能,,比如,某些屬性和方法可以是私有的,,不能被外界訪問(wèn),,通過(guò)訪問(wèn)控制,能夠?qū)?nèi)部數(shù)據(jù)提供不同級(jí)別的保護(hù),,以防止外界意外地改變或使用了私有部分,。不同的編程語(yǔ)言提供的訪問(wèn)控制等級(jí)不盡相同,但都有公有,、私有兩個(gè)等級(jí),。
類(lèi)是抽象的數(shù)據(jù)類(lèi)型,在內(nèi)存中并不存在(Python等動(dòng)態(tài)語(yǔ)言除外),,只有類(lèi)的實(shí)例存在于內(nèi)存中。
2UML類(lèi)圖
在面向?qū)ο笤O(shè)計(jì)開(kāi)發(fā)中,,通常使用UML工具來(lái)進(jìn)行分析設(shè)計(jì),。比如,可以使用UML類(lèi)圖來(lái)描述類(lèi),。
UML類(lèi)圖很簡(jiǎn)單,,用一個(gè)矩形框代表一個(gè)類(lèi),,矩形框內(nèi)部被隔為三部分:上面部分為類(lèi)的名字,中間部分為類(lèi)的屬性,,下面部分為類(lèi)的方法,。對(duì)于屬性和方法,還可以使用“+”,、“-”修飾符來(lái)表示訪問(wèn)權(quán)限,,“+”為公有屬性、“-”為私有屬性,。
如圖1所示,,該類(lèi)圖描述了一個(gè)名為“Human”的類(lèi)?!癏uman”類(lèi)抽象并封裝了“人”,;屬性“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ì)講話(huà)這一行為的抽象,,這兩個(gè)方法都是社會(huì)活動(dòng),,所以被設(shè)置為公有屬性。
設(shè)計(jì)類(lèi)的過(guò)程就是抽象的過(guò)程,,抽象的結(jié)果取決于抽象時(shí)所站的角度,,比如,如果是警察來(lái)抽象“Human”,,他可能會(huì)添加一個(gè)“isBadGuy”屬性,。
UML類(lèi)圖主要用于輔助分析和設(shè)計(jì)階段,在設(shè)計(jì)類(lèi)時(shí)應(yīng)聚焦在與當(dāng)前問(wèn)題有關(guān)的重要屬性和行為,,無(wú)關(guān)的屬性和方法統(tǒng)統(tǒng)去掉,,確保UML類(lèi)圖是簡(jiǎn)潔有效的。除非私有屬性或方法會(huì)影響到問(wèn)題的理解或者類(lèi)的實(shí)現(xiàn),,否則UML類(lèi)圖中不要出現(xiàn)私有屬性和方法,,私有屬性通常在實(shí)現(xiàn)階段才會(huì)去考慮。
UML類(lèi)圖以及其他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ǔ)言的類(lèi)封裝實(shí)現(xiàn)
很多現(xiàn)代編程語(yǔ)言都有原生的面向?qū)ο笾С?,比如C++、JAVA,、Python等,,這些編程語(yǔ)言提供了class數(shù)據(jù)類(lèi)型,在這些編程語(yǔ)言中類(lèi)實(shí)際上就是一種數(shù)據(jù)類(lèi)型,,因此能夠更好地支持面向?qū)ο缶幊獭?/p>
實(shí)際上,,面向?qū)ο笫桥c編程語(yǔ)言無(wú)關(guān)的,更像是一種思想,,且不局限于軟件開(kāi)發(fā)活動(dòng),,任何需要分析解決問(wèn)題的場(chǎng)合都可以使用面向?qū)ο蟆?/p>
C語(yǔ)言并沒(méi)有類(lèi)的概念,但是可以從類(lèi)的特性出發(fā),,利用C語(yǔ)言的某些特性來(lái)實(shí)現(xiàn)類(lèi)的用法,。關(guān)于類(lèi),首先要解決的就是封裝問(wèn)題,,類(lèi)的封裝特性需要能夠封裝屬性和方法,,還要有訪問(wèn)控制??梢允褂?h,、.c文件和結(jié)構(gòu)體來(lái)完成封裝。
下面以圖1中Human類(lèi)的C語(yǔ)言實(shí)現(xiàn)為例來(lái)敘述C語(yǔ)言的類(lèi)封裝問(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)類(lèi)名
Human類(lèi)的名稱(chēng)體現(xiàn)在human.c,、human.h以及human.h中所有全局符號(hào)的命名上,這些命名全部使用關(guān)鍵字human作為前綴,。
(2)屬性
Human類(lèi)的屬性體現(xiàn)在自定義類(lèi)型human_t中,,human_t實(shí)際上為結(jié)構(gòu)體struct human,它有兩個(gè)成員:name和_money,,分別對(duì)應(yīng)類(lèi)圖中的屬性+name和-money,,特別留意_money成員前的“_”,這是為了警示類(lèi)的使用者“此成員為私有屬性,不可使用”,。
(3)方法
Human類(lèi)的方法體現(xiàn)在human_talk()、human_buy()這兩個(gè)函數(shù)上,,分別對(duì)應(yīng)類(lèi)圖中的方法+buy()和+talk(),。此外,還可以注意到有human_init(),、human_deinit()這兩個(gè)函數(shù),,分別為Human類(lèi)的構(gòu)造、析構(gòu)方法,。構(gòu)造,、析構(gòu)方法分別用于類(lèi)對(duì)象的初始化和解初始化。
構(gòu)造函數(shù)human_init()需要用戶(hù)提供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類(lèi)有私有方法money_pay(),,則其C語(yǔ)言實(shí)現(xiàn)如下:
// human.c
static int __human_money_pay (human_t *p_this, unsignedcost)
{ … }
UML類(lèi)圖中一般不會(huì)顯式地出現(xiàn)構(gòu)造、析構(gòu)和私有這三種方法,,除非需要在類(lèi)的構(gòu)造,、析構(gòu)和實(shí)現(xiàn)上有特殊說(shuō)明。
另外需要注意的是,,這幾個(gè)方法函數(shù)的第一個(gè)參數(shù)都是human_t *類(lèi)型,,且名稱(chēng)為p_this,這是C語(yǔ)言面向?qū)ο缶幊膛c面向過(guò)程的最大不同:p_this為指向類(lèi)實(shí)例(即對(duì)象)的指針,,所有的方法操作都需要“針對(duì)”一個(gè)對(duì)象,,p_this指針由類(lèi)的構(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類(lèi)的C語(yǔ)言實(shí)現(xiàn)中,,屬性被定義為human_t中的兩個(gè)成員,而 human_t被定義在用戶(hù)可見(jiàn)的human.h中,,所以human_t是暴露給用戶(hù)的,,因此,從語(yǔ)法上講,,Human類(lèi)的兩個(gè)屬性是暴露給用戶(hù)的,,即都是公有屬性。雖然語(yǔ)法上不能支持私有,,但可以在編程規(guī)范上設(shè)定“私有屬性以短下劃線“_”開(kāi)頭”,,比如“_money”,,如此從某種意義上實(shí)現(xiàn)了屬性的訪問(wèn)控制。
在Human類(lèi)的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ì)用戶(hù)不可見(jiàn),。由此可知,,C語(yǔ)言本身就能支持方法的訪問(wèn)控制。
4結(jié)論
本文通過(guò)使用C語(yǔ)言實(shí)現(xiàn)一個(gè)Human類(lèi),,討論了如何使用C語(yǔ)言來(lái)實(shí)現(xiàn)類(lèi)的封裝特性,。在C++等面向?qū)ο笳Z(yǔ)言中,使用class對(duì)類(lèi)做了原生的支持,,使用起來(lái)非常簡(jiǎn)單,。盡管C語(yǔ)言并不是原生支持類(lèi),但通過(guò)語(yǔ)言,、概念,、規(guī)范上的處理,也能實(shí)現(xiàn)類(lèi)的封裝特性,。用C語(yǔ)言實(shí)現(xiàn)類(lèi)的封裝相當(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.