一、setter和getter的一般寫法
setter和getter器可以說是一個類最基本的東西,任何一門面向對象的語言,都又這個概念,C++、java等等。因為setter和getter是對面向對象語言封裝的最基本的支持。
在Objective-C的setter和getter器,當然也和一般的語言沒有什么不同。只不過,添加了一些自己的特性。
比如有一個實例變量:int age;
先在.h文件中聲明setter和getter器
然后在.m文件中具體實現
可以看出來,在Objective-C中setter器沒什么區別,不過getter器的方法名缺少了get,因為get...在Objective-C有別的用處,所以getter器直接寫的就是變量名。
二、調用setter和getter方法
-
一般的調用方法,是傳統的帶中括號[ ]的調用方法,比如
- 點調用的方式
oc語法關於點表達式的說明:"點表達式(.)看起來與C語言中的結構體訪問以及java語言匯總的對象訪問有點類似,其實這是oc的設計人員有意為之。如果點表達式出現在等號左邊,該屬性名稱的setter方法將被調用。如果點表達式出現在右邊,該屬性名稱的getter方法將被調用。"
三、引入屬性@property改進setter和getter
每次要為一個屬性寫上getter和setter,不得不十分麻煩,所以蘋果公司為OC引入了@property,用來改進setter和getter
- 在ios第一版中,我們為輸出口同時聲明了屬性和底層實例變量,那時,屬性是oc語言的一個新的機制,並且要求你必須聲明與之對應的實例變量,例如:
.h
.m
- 在Xcode中間的一個版本中,不再需要為屬性聲明實例變量了,因為@synthesize默認會去訪問str的同名變量,如果找不到同名變量,會自動生成一個叫做str的私有同名變量。
.h
.m
- Xcode為中間版本做了個升級版,主要考慮到getter器的方法名直接就是變量名,方法名和變量名一樣,容易讓人迷糊,所以,可以這樣優化。
.m
-
在Xcode4.5及以后的版本中,直接把@synthesize給省略
.h
編譯器會自動為你生成setter和getter方法 和 以下划線開頭的實例變量_str,不需要自己手動再去寫實例變量
在這里我說明一下@synthesize的作用:
1、一個作用就是讓編譯器為你自動生成setter與getter方法。
2、還有一個作用,可以指定與屬性對應的實例變量,
例如@synthesize str = xxx;那么self.str其實是操作的實例變量xxx,而不是_str了。
如果.m文件中寫了@synthesize str;那么生成的實例變量就是str;如果沒寫@synthesize str;那么生成的實例變量就是_str。
(注意:_str這個實例變量是不存在的).
在老式的代碼中,@property只能寫在@interface @end中,@synthesize只能寫在@implementation @end中,自從xcode 4.5及以后的版本中,@property就獨攬了@property和@synthesize的功能。
@property (nonatomic, copy) NSString *str;這句話完成了3個功能:1)生成_str成員變量的get和set方法的聲明;2)生成_str成員變量set和get方法的實現;3)生成一個_str的成員變量。(注意:這種方式生成的成員變量是private的)
四、對屬性的一些設置
1、設置訪問方法的名字
默認的getter和setter器的名稱是和變量名關聯的,一定是setVirableName和virableName,比如上面的變量age,setter是setAge,getter是age。可以通過設置@property中的setter和getter屬性來修改setter和getter器的方法名。
- getter=getterName
- setter=setterName
舉個例子:
注意:如果你設置了readonly屬性的話,那么你就不應該設置setter屬性,要不然會給出一個編譯器的警告。
2、設置只讀或讀寫
- readwrite:表示既有getter,也有setter
- readonly:表示只有getter,沒有setter
這兩個屬性是互相排斥的,只能存在一個。
五、屬性重寫setter和getter方法
使用屬性@property能夠幫我們省去了很多繁雜的工作,但有的時候我們在使用屬性的時候還是需要去重寫一下其setter和getter方法,這個時候我們應該怎么做呢
-
如果只重寫setter和getter其中之一,可以直接重寫
-
如果同時重寫setter和getter,需要加上
@synthesize propertyName = _propertyName;不然系統會不認_str。
因為如果你同時重寫了getter和setter方法,系統就不會幫你自動生成這個_str變量,所以當然報錯說不認識這個變量。所以得手動指定成員變量,然后再同時重寫了getter和setter方法。
注意事項:
在重寫set和get時,容易犯如下錯誤,會造成死循環。
1、在set方法中,self.age=age;相當於是[self setAge:age];
2、在get方法中,return self.age;相當於是[self age];