OC實例變量與屬性的訪問控制

對于剛?cè)腴TOC開發(fā)的人都有一個疑惑,就是下面這些方式創(chuàng)建實例變量有什么區(qū)別呢?PS:為了簡化,這里省略了property的修飾詞。

@interface Person : NSObject {
    @public int a;
    @protected int b;
    @private int c;
}

@property int d;

2,3,4行創(chuàng)建的是實例變量,或成員變量。對C還有印象的都知道結(jié)構(gòu)體吧,OC的類本質(zhì)上就是一個結(jié)構(gòu)體。
第7行聲明的是一個property,直譯為屬性。它與實例變量是有區(qū)別的。

  • 面向?qū)ο蟮姆馓匦?/h4>

存取一個對象的成員變量時,我們應(yīng)該使用setter和getter方法,而不是直接引用對象的成員變量。

@interface SomeClass : NSObject
- (void)setName:(NSString *)name;
- (NSString *)name;
@end

@implementation SomeClass {
    NSString *_privateName;
}

- (void)setName:(NSString *)name {
    self->_privateName = name;
}

- (NSString *)name {
    return self->_privateName;
}

@end

這是一個簡單的類,該類有一個私有的_privateName實例變量寫在@implementation里面,這個實例變量只能在內(nèi)部使用,外部無法引用。為了讓外部能存取這個實例變量,@interface里分別寫了getter和setter方法,外部通過這兩個方法來訪問對象的實例變量。這是一種基本的面向?qū)ο笤O(shè)計方式。

但是每次添加一個實例變量都要為它們創(chuàng)建對應(yīng)的setter和getter,無疑會添加大量的工作量,所以蘋果工程師在后續(xù)的xcode里添加一些語法支持來降低輸入量,這就是property的作用。

@interface SomeClass : NSObject
@property NSString *name;
@end

@implementation SomeClass
@end

可以看到的是,這里一行就可以搞定了。簡單來說聲明一個property為我們省下了自行添加實例變量和添加setter和getter的時間。值得注意的是,添加property后,系統(tǒng)會自動生成對應(yīng)的實例變量,該實例變量的名字是property名字前加下劃線,如_name

與property相關(guān)的是點語法。

  SomeClass *a = [SomeClass new];
  a.name = @"just a";
  NSString *name = a.name;

點語法并不如外表那樣看上去那么簡單,它可以被展開的。

  [a setName:@"just a"];
  NSString *name = [a name];

這兩個方法是不是很熟識了?上面已經(jīng)說過了,是setter和getter,點語法是將它們簡化了。

  • 實例變量的訪問控制

上面的例子里提到在@implementation里聲明的實例變量是只能在內(nèi)部訪問的,是私有的。另外這種聲明是不能被子類引用的。

實例變量有三種常見的訪問修飾詞

  • @public, 這個聲明的實例變量可以在任何地方訪問。
  • @protected,系統(tǒng)默認的,當沒有指定時會默認這個。不能被外部訪問,但能被子類訪問。
  • @private,完全私有,這個就等同與聲明在@implementation里。

很久很久以前,程序員都習(xí)慣在@interface里聲明所有實例變量,并為其添加訪問控制。那時到底基于什么原因這樣寫呢?我也搞不清楚,因為太遠了。

對于現(xiàn)在來說,好的習(xí)慣是在類的@interface里聲明必要的property,保持接口文件的可閱讀性。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容