@property和@protocol小記

眾所周知,@property是Objective-C語(yǔ)言的關(guān)鍵字,在xcode4.5之前的版本需要與@synthesize配對(duì)使用,之后則可以單獨(dú)使用。作用是通過合成存取方法來(lái)封裝對(duì)象中的數(shù)據(jù),通常被稱為屬性。因此,@property 的本質(zhì)就是ivar(實(shí)例變量) 和 getter/setter(存取方法)。編譯器是根據(jù)Objective-C嚴(yán)格的命名規(guī)范來(lái)生成存取方法的,因此實(shí)例變量前面會(huì)加下劃線(_),gettter方法就是屬性名,setter方法就是在屬性名前面加set。

下面并不打算討論@property的細(xì)節(jié)問題,而是著重說(shuō)明一下@property在遇到@protocol時(shí)的一些小的變化。對(duì)于@protocol,在iOS開發(fā)中見得最多的應(yīng)該是把它用于代理,例如:

UITableView的代理
UITableViewDelegate,UITableViewdataSource,
UIScrollView的代理
UIScrollViewDelegate等等。

而@protocol最重要的還應(yīng)該用于作為接口(或者叫抽象基類)。由于Objective-C語(yǔ)言不存在多重繼承一說(shuō),因此抽象基類很少這樣叫。常被提及的應(yīng)該是面向協(xié)議編程。

關(guān)于@protocol的簡(jiǎn)單使用:


// Parent.h
@protocol Parent <NSObject>
- (void)setName:(NSString *)name;
- (NSString *)name;
@end

// Child.h
@interface Child : NSObject<Parent>{
    NSString *name_;
}

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

@end

// Child.m
@implementation Child

- (void)setName:(NSString *)name {
    name_ = name;
}

- (NSString *)name {
    return name_;
}
@end

以上示例,定義協(xié)議Parent,Child遵從這個(gè)協(xié)議就必須由自己去實(shí)現(xiàn),這是理所應(yīng)當(dāng)?shù)氖虑椤H绻蝗?shí)現(xiàn):

警告信息:Method 'setName:' in protocol 'Parent' not implemented
Method 'name:' in protocol 'Parent' not implemented

意思是:Parent協(xié)議中的方法setName和name沒有實(shí)現(xiàn)

假如

協(xié)議Parent中使用@property呢?協(xié)議中明確說(shuō)明不能聲明成員變量,@property并不是,應(yīng)該說(shuō)并不僅僅是。代碼如下:

// Parent.h
@protocol Parent <NSObject>
@property (copy, nonatomic) NSString *name;
@end

// Child.h
@interface Child : NSObject<Parent>
// 假如這里面什么也不寫 
//@property (copy, nonatomic) NSString *name;

// 假如這里面這樣寫是否正確?
- (void)setName:(NSString *)name;
- (NSString *)name;

@end

// Child.m
@implementation Child

@end

答案是:兩種寫法都可以,不過什么也不寫編譯器一定會(huì)發(fā)出警告,這是毋庸置疑的。只是,警告與上面有所不同。

警告信息:Auto property synthesis will not synthesize property 'name' declared in protocol 'Parent'
意思是:Parent協(xié)議中的屬性name不會(huì)被自動(dòng)合成,也就是不會(huì)自動(dòng)合成存取方法和實(shí)例變量。

再次假如

協(xié)議Parent中使用setName和name,Child遵從Parent協(xié)議,但是使用@property來(lái)合成setName和name方法,同樣可行。

因此,結(jié)論是@property是可以在@protocol中使用的,只是由于@protocol特性的限制,@property在@protocol中并不會(huì)合成實(shí)例變量,只會(huì)合成存取方法。因此在@protocol中使用了@property,對(duì)應(yīng)的在遵從此協(xié)議的類中,如果不需要重寫setter和getter的情況寫也使用@property交給編譯器自動(dòng)合成。

注意:@property合成的實(shí)例變量只有自己可以直接訪問,也就是(_XX = ?),如果還有子類繼承Child,則只能通過點(diǎn)語(yǔ)法訪問,或者直接調(diào)用setter和getter方法訪問。

最后針對(duì)Objective-C協(xié)議補(bǔ)充說(shuō)明

1)Protocol:就一個(gè)用途,用來(lái)聲明一大堆的方法(不能聲明成員變量),不能寫實(shí)現(xiàn)

2)只要某個(gè)類遵守了這個(gè)協(xié)議,就擁有了這個(gè)協(xié)議中的所有方法聲明

3)只要父類遵守了某個(gè)協(xié)議,那么子類也遵守

4)Protocol聲明的方法可以讓任何類去實(shí)現(xiàn),protocol就是協(xié)議

5)OC不能繼承多個(gè)類(多繼承)但是能夠遵守多個(gè)協(xié)議,繼承(:),遵守協(xié)議(<>)

6)基協(xié)議:<NSObject>基協(xié)議,是最根本最基本的協(xié)議,其中聲明了很多最基本的方法

7)協(xié)議可以遵守協(xié)議,一個(gè)協(xié)議遵守了另一個(gè)協(xié)議,就可以擁有另一個(gè)協(xié)議中的方法聲明(稱為協(xié)議繼承)

最后編輯于
?著作權(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),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 出題者簡(jiǎn)介: 孫源(sunnyxx),目前就職于百度,負(fù)責(zé)百度知道 iOS 客戶端的開發(fā)工作,對(duì)技術(shù)喜歡刨根問底和...
    戈多_于勒閱讀 1,866評(píng)論 0 5
  • 下雨天 看著旁邊有個(gè)光頭正對(duì)著草坪站著,下雨天的,覺得奇怪,仔細(xì)地看了好久。你說(shuō),別看了,人家在撒尿。我說(shuō)我知...
    少女與野花閱讀 297評(píng)論 0 0
  • 上海的季節(jié)變化很有意思 沒什么規(guī)律(是不是很神秘,很因垂斯汀) 連著下了好幾天大雨后 好不容易盼來(lái)的周六 變天了 ...
    張艾拉閱讀 253評(píng)論 2 0

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