新聞中心
封裝(Encapsulation)和信息隱藏,這兩個詞,我想大家都不會陌生。但是,有很多開發(fā)人員并沒有深入的了解,甚至存在一些誤區(qū)。今天就專門來說一下。

一、封裝
1、什么是封裝?
從字面意思來看,封裝就是把一些相關的 東西打包成一坨(看到“坨”這個量詞,不要想歪了)?!胺庋b”最廣為人知的例子,就是在面向?qū)ο缶幊蹋ㄒ韵潞喎QOOP)里面,把數(shù)據(jù)和針對該數(shù)據(jù)的操作,統(tǒng)一到一個class里。
2、封裝有啥好處?
那封裝有啥好處捏?一個主要的好處,就是增加軟件代碼的內(nèi)聚性。通過增加內(nèi)聚性,進而提高可復用性和可維護性。
3、封裝的手段
很多人把封裝的概念局限于類,認為只有OO中的class才算是封裝。這實際上是片面滴!在很多不使用"類"的場合,一樣能采用封裝的手法。下面俺隨手舉幾個和OO無關的例子:
a、通過文件
比如C和C++支持對頭文件的包含(#include)。因此,可以把一些相關的常量定義、類型定義、函數(shù)聲明,統(tǒng)統(tǒng)封裝 到某個頭文件中。
b、通過namespace/package/module
C++的namespace、Java的package、Python的module,想必各自的開發(fā)人員都很熟悉。這些語法雖然稱呼各不相同,但具有相同的本質(zhì)。因此,也可以利用這些語法,來進行封裝。
二、信息隱藏
1、什么是信息隱藏?
“信息隱藏”——顧名思義——就是把不該暴露的信息藏起來。說到信息隱藏,很多人自然而然地,就聯(lián)想到某些OO語言(比如C++、Java)提供的,諸如private、protected之類的關鍵字。這些關鍵字可以通過訪問控制,來達到信息隱藏的目的。
2、信息隱藏有啥好處?
信息隱藏的好處,正好和“封裝”的好處相呼應。封裝是為了提高內(nèi)聚性;而信息隱藏是為了降低耦合性。通過降低耦合,一樣可以達到提高可復用性、可維護性這2個目的。
3、信息隱藏的手段
和封裝類似,很多程序員也把信息隱藏的概念片面化——認為信息隱藏僅限于private和protected關鍵字。所以,俺再隨手舉幾個其它的信息隱藏手段。
a、通過接口類
可以通過定義接口類(Java中的interface、C++中的純虛類)來實現(xiàn)信息隱藏。具體實現(xiàn)如下:
定義一個接口類,僅包含一些公有的成員函數(shù)的聲明 (Java的abstract函數(shù),C++的純虛函數(shù)),沒有任何函數(shù)實現(xiàn),也沒有任何成員變量。然后把具體的實現(xiàn)代碼放到該接口類的一個派生子類中。
由于調(diào)用者只看到接口類,看不到實現(xiàn)類。所以,同樣可以達到信息隱藏。在某些情況下,使用這種手段達到的效果,會比基于訪問控制(使用private關鍵字)的效果,更好。
不過這種手段依賴于語言的支持。使用該手法的編程語言,至少要支持繼承、虛函數(shù)等語法。
b、通過pimpl手法
pimpl手法也叫作“Opaque Pointer”手法。和接口類的手法不同,pimpl手法不需要靠繼承、虛函數(shù)等語法的支持,因此對諸如C語言來說,很有用。
三、一些理解上的誤區(qū)
介紹完一些基本概念,再來說一下,關于封裝、信息隱藏的一些常見誤區(qū)。
1、把封裝等同于信息隱藏
這是混淆最嚴重的一個誤區(qū)——很多初學OOP的同學都把封裝和信息隱藏混為一談。希望經(jīng)過俺前面的一番解釋,有些人能搞明白其中的差異。順便提一下,有個老外寫了篇小有名氣的文章——“Encapsulation is not information hiding ”。洋文好的同學,可以去瞅一瞅。
2、把封裝看得太狹隘
其實前面已經(jīng)通過舉例,駁斥了狹隘看待封裝的誤區(qū)。此處不再啰嗦。
3、把信息隱藏看得太狹隘
前面已經(jīng)通過舉例,駁斥了狹隘看待信息隱藏的誤區(qū)。此處不再啰嗦。
4、混淆可訪問性和可見性
考慮到某些網(wǎng)友可能連這兩者的區(qū)別都不太清楚,先簡單解釋一下。所謂可訪問性,就是可以對某個東西進行讀/寫操作;所謂可見性,就是能夠感覺到某個東西的存在。
前面談到信息隱藏時,我們提及了通過訪問控制的關鍵字(private、protected)來達到信息隱藏的目的。有很多同學認為這幾個關鍵字不光禁止了可訪問性(accessibility),還禁止了可見性(visibility)。其實也不盡然。不同的編程語言,對這兩者的處理是不同滴。比如在 C++語言中,類的私有成員雖然不可訪問,但還是可見的。此話怎講捏?請看下面的例子:
- int n = 0;
- class Parent
- {
- public:
- Parent()
- {
- n = 1;
- }
- private:
- int n;
- };
- class Child : public Parent
- {
- public:
- Child()
- {
- }
- void Func()
- {
- ::printf("%d", n);
- }
- };
- int main()
- {
- Child c;
- c.Func();
- return 0;
- }
如果俺問列位看官,程序執(zhí)行后會打印出啥?相信一多半的同學會回答:“打印0”。
但是,真相是:該程序根本在編譯時就報錯了。
問題在于,父類的私有成員變量n雖然對子類是無法訪問的,但依然是可見的(可感知的)。所以,對于那個printf語句,編譯器會認為是企圖訪問父類的私有成員,故而報錯。
再悄悄跟大伙兒說一下,這個例子是俺從C++它爹所寫的《The Design and Evolution of C++》里面剽竊滴。
四、結尾
今天的話題,基本上到此結束了。***,俺想提醒列位看官注意一下:象封裝和信息隱藏,都屬于編程的基本功,為啥很多開發(fā)人員都沒有想透徹捏?
如果大家有什么不明白的,可以參見原文,下面是原文地址。
本文出處:http://blog.csdn.net/program_think/archive/2010/08/29/5846881.aspx
【編輯推薦】
- Javascript面向?qū)ο缶幊蹋ㄒ唬?封裝
- 基本的封裝Ajax之一
- 淺談C++調(diào)用C#的DLL程序方法
- C++多態(tài)技術的實現(xiàn)和反思
- C++連接mysql數(shù)據(jù)庫的兩種方法
當前標題:分析有關封裝和信息隱藏的誤區(qū)
轉(zhuǎn)載源于:http://m.fisionsoft.com.cn/article/cohspjj.html


咨詢
建站咨詢
