有個class表示網頁瀏覽器,現在要寫一個函數用來清除瀏覽器的高速緩存區、URLs、cookies。請問是使用member函數好,還是使用non-member函數好?
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
- class WebBrowser
- {
- public:
- void clearCache();
- void clearHistory();
- void removeCookies();
- };
- //member實現方式
- class WebBrowser
- {
- public:
- void clearEverything();
- };
- //non-member實現方式
- void clearBrowser(WebBrowser& wb)
- {
- wb.clearCache();
- wb.clearHistory();
- wb.removeCookies();
- }
面向對象守則要求數據應該儘可能被封裝,
member函數帶來的封裝型比non-member函數低[1]。此外,提供non-member函數可允許對WebBrowser相關機能有較大的包裹彈性,而那最終導致較低的編譯相依度,因此,在許多方面non-member做法比member做法好。封裝:意味着不可見。愈多東西被封裝,愈少人看到,愈大的彈性去變化,因爲我們的改變僅僅直接影響到改變的那些人事物。愈多東西被封裝,我們改變那些東西的能力就愈大。這就是我們推崇封裝的原因:它使我們能夠改變事物而隻影響有限客戶[2]。
讓函數成爲non-member,並不意味着它不可以是另一個class的member[3]。在C++中,可以使用namespace對non-member與class[4]進行包含,除了看上去更自然以外,namespace[5]還能夠跨越多個源碼文件[6]。
[2] 作爲一種粗糙的量測:愈多函數可以訪問一個數據,則數據的封裝性愈低。
[3] 在Java裏面,所有函數必須定義於class中。clearBrowser很可能成爲一個工具類(utility class)的static member函數。
[4] Class定義式對客戶而言是不能擴展的,你可以繼承它,但是class內部的private成員仍然不能訪問。所以,我們寧可使用non-member函數,增加封裝性、機能擴充性。
[5] Class是不能分割的,而將所有便利函數放在多個文件、一個namespace中,意味着客戶可以輕鬆擴展它們:他們只需在namespace中建立文件、包含函數聲明,新函數就像其它舊有的便利函數那樣整合一體。
[6] 因爲你在實現的時候,可能將cookie相關類放在一個文件中,將bookmark相關類放在另一個文件中,而namespace可以組織它們。在stl中,每個頭文件聲明std的某些機能。