IOS 開發學習總結objective-c物件導向之——封裝和存取控制符

來源:互聯網
上載者:User

IOS 開發學習總結objective-c物件導向之——封裝和存取控制符
封裝封裝的定義

物件導向的三大特徵(封裝,繼承,多態)之一。指的是:將對象的狀態資訊隱藏在對象內部,不允許外部程式直接存取對象內部資訊,而是通過該類所提供的方法來實現對內部資訊的操作和訪問。

良好的封裝,可以實現的目的

對一個類或對象實現良好的封裝,可以實現的目的有:
1. 隱藏類的實現細節;
2. 使使用者只能通過事先預定的方法來訪問資料,從而可以在該方法裡加入控制邏輯,限制對成員變數的不合理訪問。
3. 可進行資料檢查,有利於保證對象資訊的完整性;
4. 便於修改。提高代碼可維護性。

如何?良好的封裝把對象的成員變數和實現細節隱藏起來,不允許外部直接存取。 把方法暴露出來,讓方法來控制對這些成員變數進行安全的訪問和操作。存取控制符

封裝需要使用 objective-c 提供的4個存取控制符:@private,@package,@protected和@public。它們分別代表了4個存取控制層級。
它們的存取控制層級由小到大依次如:

4個存取控制符說明如下:
1. @private:【當前類存取權限】,只能在當前類內部被訪問。用於徹底隱藏成員變數。類的實現部分定義的成員變數相當於預設用這種存取權限。
2. @package:【與映像存取權限相同】用於部分隱藏成員變數。如果類的成員變數使用@package 存取控制符來限制,則這個成員可以在當前類及當前類實現的同一個映像的任意地方訪問。
3. @protected:【子類存取權限】用於部分隱藏成員變數。如果類的成員變數使用@protected 存取控制符來限制,則這個成員可以在當前類,當前類的子類的任意地方訪問。在類的介面部分定義的成員變數預設使用這種存取權限。<喎?http://www.bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vc3Ryb25nPjxiciAvPg0KNC4gQHB1YmxpY6O6ob65q7myt8POysioz96hvyzTw8v8z97WxrXEwOC1xLPJ1LG/ydLU1NrIztLitdi3vbfDzsossru53MrHt/G0ptPazazSu9Ozz/HW0CzSsrK7udzKx7fxvt/T0LzMs9C52M+1oaM8YnIgLz4NCtfbyc8sztLDx9PDzbyx7b340NDPwtfcveGjujxiciAvPg0KPGltZyBhbHQ9"這裡寫圖片描述" src="http://www.bkjia.com/uploads/allimg/151012/0516024627-1.png" title="\" />
那麼,局部變數能否被存取控制符修飾呢?
答案是不能。因為對於局部變數而言,它的範圍是它所在的方法,不可能被其他類訪問。所以不能用存取控制符來修飾。而存取控制符用於控制類的成員變數是否可以被其他類訪問。
樣本程式:
FKPerson.h檔案

#import @interface FKPerson : NSObject{ // 使用@private限制成員變數 @private NSString* _name; int _age;}//提供方法來操作name Field- (void) setName: (NSString*) name;// 提供方法來擷取_name成員變數的值- (NSString*) name;// 提供方法來設定age成員變數- (void) setAge:(int) age;// 提供方法來擷取_age成員變數的值- (int) age;@end

FKPerson.m檔案

#import FKPerson.h@implementation FKPerson// 提供方法來設定_name成員變數- (void) setName: (NSString*) name{ //執行合理性校正,要求使用者名稱必須在2~6位之間 if ([name length] > 6 || [name length] < 2) { NSLog(@您設定的人名不符合要求); return; } else { _name = name; }}// 提供方法來擷取_name成員變數的值- (NSString*) name{ return _name;}// 提供方法來設定age成員變數- (void) setAge:(int) age{ if(_age != age) { //執行合理性校正,要求使用者年齡必須在0~100之間 if (age > 100 || age < 0) { NSLog(@您設定的年齡不合法); return; } else { _age = age; } }}// 提供方法來擷取_age成員變數的值- (int) age{ return _age;}@end

【知識切入】存取權限控制符的作用範圍是如何劃分的呢?
@private,@package,@protected和@public,這4個許可權控制符的作用範圍是這樣的,從它們出現的位置開始,到下一個許可權控制符出現或右邊花括弧之間的成員變數,都受到該存取權限控制符的控制。
oc 中成員變數的 setter 和 getter 方法有非常重要的意義。如,某個類中包含了一個名為_sun的 Field, 則其對應的 setter 和 getter 方法名應為 setSun 和 sun(setter 方法名為成員變數名首字母大寫,並在前面分別增加 set 動詞,getter 方法名為去掉畫線首碼)
樣本程式:

#import FKPerson.hint main(int argc , char * argv[]){ @autoreleasepool{ FKPerson* p = [[FKPerson alloc] init]; // 因為age成員變數已被隱藏,所以下面語句將出現編譯錯誤。// p->_age = 1000; // 下面語句編譯不會出現錯誤,但運行時將提示出入的age成員變數不合法 // 程式不會修改p的age成員變數 [p setAge: 1000]; // 訪問p的age成員變數也必須通過其對應的getter方法 // 因為上面從未成功設定p的age成員變數,故此處輸出0 NSLog(@未能設定age成員變數時:%d , [p age]); // 成功修改p的age成員變數 [p setAge:30]; //因為上面成功設定了p的age成員變數,故此處輸出30 NSLog(@成功設定age成員變數後:%d , [p age]); // 不能直接操作p的name成員變數,只能通過其對應的setter方法 // 因為李剛字串長度滿足2~6,所以可以成功設定 [p setName:@李剛]; NSLog(@成功設定name成員變數後:%@ , [p name]); }}

這裡的 FKperson 對象已經不能再直接修改它的成員變數。只能通過各自對應的 setter,getter 方法進行設定成員變數的值。當 setter 方法設定響應的成員變數的時,允許程式員在 setter 方法中增加自己的控制邏輯,保證這些成員變數不會出現與實際不符的情況。

存取控制符使用的基本原則類裡絕大部分成員變數都應該使用@private 限制。
工具方法(指只是輔助實現該類的其他方法的方法)應該隱藏在該類的內部,此時應把這些方法定義愛類實現部分。 如果某個類主要作為其他類的父類,該類裡包含成員變數希望被子類訪問,則可以考慮用@protected 限制這些成員變數。 暴露出來給其他類自由調用的方法,應該先在類介面部分定義,然後在類實現部分實現它們。理解@package

受@package限制的成員變數,步進可以在當前類中訪問,也可以在相同映像的其他程式中訪問。那麼:什麼是”同一映像”呢?
同一映像,簡單的說,就是編譯後產生的同一個架構或者同一個執行檔案。
比如說,我們想開發一個基礎架構,若用@private 限制成員變數,則限制太死——考慮該架構中的其他類,其他函數可能需要直接存取該成員變數,但該架構又不希望其他外部程式訪問該成員變數。此時考慮用@package 來限制成員變數。
當編譯器把@package限制的成員變數所在的類,其他類和函數編譯成一個架構庫之後,那麼這些類,函數都在同一個映像中,此時這些類,函數都可以自由訪問由@ package 限制的成員變數。但是,其他程式引用這個架構庫時,由於其他程式只是依賴這個架構庫,其他程式與該架構庫就不在同一映像中,因此,其他程式無法訪問這個@ package 限制的成員變數。
樣本程式:
FKApple.h檔案

#import @interface FKApple : NSObject{    // 使用@package限制成員變數    @package    double _weight;}@end

FKApple.m 檔案

#import FKApple.h@implementation FKApple@end

FKAppleTest.m檔案

#import FKApple.hint main(int argc , char * argv[]){    @autoreleasepool{        FKApple* apple = [[FKApple alloc] init];        // 下面程式程式直接存取@package限制的成員變數,最終賦值成功        apple->_weight = 30.4;        NSLog(@apple的重量為:%g , apple->_weight);    }}

運行編譯後,編譯器會把FKApple.h,FKApple.m,FKAppleTest.m檔案編譯成一個執行檔案,由於FKApple類和 main() 函數同在一個映像中,因此main() 函數可以自由訪問FKApple類中被@package 限制的成員變數。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.