天天看點

《C++面向對象高效程式設計(第2版)》——2.4 保護實作

本節書摘來自異步社群出版社《c++面向對象高效程式設計(第2版)》一書中的第章,第2.4節,作者: 【美】kayshav dattatri,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。

c++面向對象高效程式設計(第2版)

傳統的面向過程程式設計,缺乏對實作者的保護。如果實作在生存期内無法保證自身的完整性,這樣的實作則毫無用處。假如有人篡改了汽車速度表的傳感裝置會怎樣?速度表将無法正确顯示汽車的速度。假如自動櫃員機(atm)允許客戶可以直接操作他人的賬戶會怎樣?假如允許消費者不通過電源插座,直接使用電力電纜會怎樣?

以上這些情況都有一個共同點,即它們隻可通過特定的方式(接口)使用,沒有其他方法(電腦黑客除外!)可繞過接口直接通向實作。駕駛員不能篡改速度表,至少是很難1。atm允許個人對自己的賬戶執行某些受限操作,但不允許客戶接觸他人的賬戶。同樣,直接從家門前的電線杆上(或配電箱中)接電是非法的。

這些例子中,接口(速度表、atm、電源插座)都由實作支援,而且該實作由對應的接口來保護(即接口提供一個清晰且定義明确的方法通路實作)。換言之,實作以特定方式工作,并跟蹤自身的狀态。另外,實作假設它的狀态僅能通過接口更改,如果違反此前提條件(即不知何故,實作的狀态被直接從外部更改,并未通過提供的接口更改),則無法保證實作進行正确地操作。從接口的角度看,實作應通過公共接口運作(或由公共接口通路),以確定實作的完整性。

回顧一下影碟播放機的例子,當我們按下play時,ld播放機的實作将進行檢查,以確定:

(a)已載入碟片;

(b)已關閉碟片托架(或托盤)。

如果滿足了以上條件,ld播放機将激活雷射束裝置和馬達驅動器等,并開始讀碟。為了檢測條件(a)和(b),ld播放機可能使用某些微動開關,而且假設任何人都無法直接操作這些開關,隻有實作才能控制微動開關。[ 這與我們常見的洗衣機和烘幹機的關門傳感器類似。這些電器附帶的說明書中會清楚地說明,隻有關閉洗衣機的門,洗衣機才可運轉。如果仔細檢視會發現,在洗衣機門的下面或後面有一個小型傳感器。洗衣機門關閉時,開關被壓低,說明門已關閉。如果好奇心驅使你按下開關,可以确信洗衣機在門未關閉的情況下,将開始運轉!此時你已經繞過洗衣機的接口直接操作,而這樣的行為可能導緻你受傷或洗衣機受損。] 如果違反了這個假設,将無法保證播放機按指定說明運作。如果我們手動操控這些開關,愚笨的播放機則相信碟片已載入,并且托架已關閉;然後我們按下play按鈕,播放機一定會啟動雷射束裝置,這可能會對播放機和使用者造成不可挽回的損失(萬幸的是,播放機的構造不會讓這樣的情況發生)。

如果使用者按已釋出的接口(published interface)操作(即按照說明使用),則不會出現這種情況。

《C++面向對象高效程式設計(第2版)》——2.4 保護實作

圖2-3

資料抽象引出了相關的概念:資料封裝(data encapsulation)。隻要存在由實作支援的帶接口的對象,就一定存在實作隐藏(implementation hiding)(也稱為資訊隐藏)。有些資訊對實作而言相當重要,但是對使用接口的使用者而言卻毫無價值,這些資訊将被隐藏在實作中。實作由接口封裝,而且接口是通路該實作的唯一合法途徑(見圖2-3)。

這就相當于說:通過門是進入房間的唯一的途徑。ld播放機把雷射束裝置、馬達和電子元件封裝在内。被封裝的項很可能是另一個對象(或一組對象),而馬達和雷射束的确是其他類的對象。注意,被封裝的資料對于對象的實作極其重要。進一步而言,實作必須維護被封裝資訊的完整(或正确的狀态)。

繼續閱讀