Objective-C中類的成員變量與屬性

在Objective-C的類與對(duì)象的概念中. 成員變量與屬性的區(qū)別與聯(lián)系一直沒有搞清楚. 直到學(xué)習(xí)了[慕課網(wǎng)](http://imooc.com)上的這個(gè)課程[Objective-C面向?qū)ο蟪躞w驗(yàn)](http://imooc.com/video/7290), 才算真正有了點(diǎn)感覺了. 最關(guān)鍵的結(jié)論就是: ***類內(nèi)使用成員變量{}, 類外使用屬性@property***.

## 成員變量 ##

### 成員變量及其get方法. ###

首先, 我們來看下基本的類成員變量及其使用.

```objective-c

// People.h

@interface People : NSObject

{

NSString *_peopleName;

}

@end

```

在.m中不做任何事情, 然后在main.m調(diào)用_peopleName成員變量,

(下圖可以看出, 調(diào)用類的成員變量時(shí), 使用 . 語法符號(hào)會(huì)出錯(cuò), 必須***使用->來調(diào)用***):

![調(diào)用類的成員變量1](http://img.blog.csdn.net/20150506155223387)

改為->, 調(diào)用p1->_peopleName的結(jié)果如下:

![調(diào)用類的成員變量2](http://img.blog.csdn.net/20150506155442148)

即, 該_peopleName默認(rèn)是protected, 外部調(diào)用需要設(shè)置為***@public***. 改動(dòng)一下:

```objective-c

// People.h

@interface People : NSObject

{

@public

NSString *_peopleName;

}

@end

```

調(diào)用p1->_peopleName的結(jié)果如下:

```objective-c

2015-05-06 15:58:41.039 memberAndProperty[2851:304100] p1._peopleName : (null)

```

### 類內(nèi)部使用成員變量

如果想在init中初始化_peopleName, 則在People.m中:

```objective-c

// People.m

- (instancetype)init

{

self = [super init];

if (self) {

_peopleName = @"people name 1";

}

return self;

}

```

調(diào)用p1->_peopleName的結(jié)果如下:

```objective-c

2015-05-06 16:01:36.974 memberAndProperty[2895:306281] p1._peopleName : people name 1

```

其他使用該成員變量的類內(nèi)部方法都是類似的用法.

### set方法

以上是對(duì)類成員變量_peopleName的調(diào)用, 如果想要對(duì)其附新值呢?

```objective-c

// main.m

People *p1 = [[People alloc] init];

NSLog(@"p1._peopleName : %@", p1->_peopleName);

p1->_peopleName = @"people name 2";

NSLog(@"p1._peopleName : %@", p1->_peopleName);

```

結(jié)果:

```objective-c

2015-05-06 16:05:34.915 memberAndProperty[2931:309406] p1._peopleName : people name 1

2015-05-06 16:05:34.916 memberAndProperty[2931:309406] p1._peopleName : people name 2

```

以上可見, 將_peopleName設(shè)置為@public之后, 可在類外對(duì)其進(jìn)行g(shù)et/set操作, 直接調(diào)用或賦值即可.

但***不推薦使用p1->_peopleName***這樣的形式. 因?yàn)? 這樣就不符合我們所說的

***"類內(nèi)使用成員變量{}, 類外使用屬性@property***"的結(jié)論了. 且將成員變量_peopleName設(shè)為@public會(huì)很不安全.

## 自定義成員變量的get/set方法

仍然將成員變量_peopleName默認(rèn)為@protected, 從類內(nèi)部的方法中對(duì)_peopleName進(jìn)行讀取或賦值, 然后間接傳遞至類外部, 是一個(gè)不錯(cuò)的選擇.

首先, 在.h中聲明getName和setName方法:

```objective-c

// People.h

@interface People : NSObject

{

NSString *_peopleName;

}

-(NSString *)getName;

-(void)setName:(NSString *)name;

@end

```

在.m中, get/set這兩個(gè)方法是以***在類內(nèi)部對(duì)成員變量_peopleName進(jìn)行調(diào)用或賦值***的方式來實(shí)現(xiàn)的.

```objective-c

// People.m

-(NSString *)getName {

return _peopleName;

}

-(void)setName:(NSString *)name {

_peopleName = name;

}

```

那么, 調(diào)用的時(shí)候就非常方便了:

```objective-c

// main.m

People *p1 = [[People alloc] init];

NSLog(@"p1.getName : %@", p1.getName);

[p1 setName:@"people name 2"];

NSLog(@"p1.getName : %@", p1.getName);

```

結(jié)果如下:

```objective-c

2015-05-06 16:25:36.019 memberAndProperty[3036:320317] p1.getName : people name 1

2015-05-06 16:25:36.020 memberAndProperty[3036:320317] p1.getName : people name 2

```

使用自定義的get/set, 從類內(nèi)部調(diào)用成員變量是一種比較常見的方式. 但需手動(dòng)添加這兩個(gè)方法.

## 屬性

那么, 有沒有更加簡便的方法呢? 或者說, get/set這種非常常見的操作, 能不能默認(rèn)提供給我們呢? 答案是肯定的!

在新的iOS SDK中, 使用@property來定義類的屬性, 是專用于從類外部對(duì)其進(jìn)行調(diào)用或賦值的.

在.h中先聲明peopleName屬性:

```objective-c

// People.h

@interface People : NSObject

{

NSString *_peopleName;

}

@property(nonatomic, strong) NSString *peopleName;

// nonatomic 非原子性訪問, 不加同步機(jī)制, 多線程并非訪問時(shí)可提高性能

// strong 相當(dāng)于一個(gè)深拷貝的操作

@end

```

在.m中使用@synthesize指令將peopleName屬性與_peopleName成員變量關(guān)聯(lián)起來:

```objective-c

// People.m

@implementation People

@synthesize peopleName = _peopleName;

- (instancetype)init

{

self = [super init];

if (self) {

_peopleName = @"people name 1";

}

return self;

}

@end

```

即, 編譯器遇到@synthesize peopleName = _peopleName;時(shí), 會(huì)自動(dòng)生成對(duì)peopleName的get/set方法.

且這里的下劃線_是必不可少的, 否則就不能正確地將屬性與成員變量關(guān)聯(lián)起來.

然后, 我們直接調(diào)用即可:

```objective-c

// main.m

People *p1 = [[People alloc] init];

NSLog(@"p1.peopleName : %@", p1.peopleName);

p1.peopleName = @"people name 2";

NSLog(@"p1.peopleName : %@", p1.peopleName);

```

結(jié)果如下:

```objective-c

2015-05-06 16:32:29.142 memberAndProperty[3094:325295] p1.peopleName : people name 1

2015-05-06 16:32:29.143 memberAndProperty[3094:325295] p1.peopleName : people name 2

```

實(shí)際上, 編譯器比我們想象中更聰明, 在.h文件中的{ NSString *_peopleName; }這個(gè)成員變量不需要聲明也可以. 僅僅聲明了@property(nonatomic, strong) NSString *peopleName;這個(gè)屬性, xcode也會(huì)默認(rèn)自動(dòng)為我們聲明一個(gè)該類的_peopleName成員變量, 及隱藏的get/set方法. 這里, 就體現(xiàn)出了下劃線 _ 的作用了.

## 結(jié)論

結(jié)論依然是:? ***類內(nèi)使用成員變量{}, 類外使用屬性@property***.

因此在類外的話, 強(qiáng)烈推薦使用屬性@property.

而如果非要在類外使用成員變量{}, 則要么將該成員變量設(shè)為@public, 要么自定義其get/set方法, 利用這兩個(gè)方法從類內(nèi)部對(duì)成員變量進(jìn)行調(diào)用或賦值. 這兩種方法各自的弊端及使用請(qǐng)參考以上內(nèi)容.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容