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