標籤:
在Java中,特別是一個標準的POJO類,我們定義了一些屬性,然後針對每個屬性產生相應的getter和setter.例如:
package com.demo;/** * 手機類 * @author liuzc */public class Phone {private String color; //顏色private String os; //系統private String brand; //品牌/******* Getter & Setter *******/public String getColor() {return color;}public void setColor(String color) {this.color = color;}public String getOs() {return os;}public void setOs(String os) {this.os = os;}public String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}
在Objective-C中,類的屬性預設是protected的,也就是說只有該類以及它的子類才能存取它,如果要給外部使用的話,則需要來幫它加個setter/getter。使用Objective-C我們可以將上面的代碼改寫為:
@implementation Phone{ NSString *color; NSString *brand; NSString *os;}-(NSString*) color{ return color;}-(NSString*) brand{ return brand;}-(NSString*) os{ return os;}-(void) setColor:(NSString*) _color{ color=_color;}-(void) setBrand:(NSString*) _brand{ brand=_brand;}-(void) setOs:(NSString*) _os{ os=_os;}@end
需要注意的是,在Objective C中,get有著特殊的含義,所以getter方法直接使用屬性名稱,而不是使用get然後再加上屬性名稱。上面僅僅只是三個屬性,如果有10個、20個屬性,是不是也需要寫大量的代碼呢?
Objective C 2.0 為我們提供了@property和@synthesize。它大大簡化了我們建立資料成員讀寫函數的過程,更為關鍵的是它提供了一種更為簡潔,易於理解的方式來訪問資料成員。
上面的代碼我們可以簡化為:
Phone.h
@interface Phone : NSObject@property NSString *color;@property NSString *brand;@property NSString *os;@end
Phone.m
#import "Phone.h"@implementation Phone@synthesize color;@synthesize brand;@synthesize os;@end
@property的文法:
其中attribute有如下幾種取值,各個attribute的含義涉及到Objective-C中記憶體管理的相關知識,後面會有詳細的講解,所以這裡只是簡單的介紹.只有有Objective-C的記憶體管理有了比較全面的瞭解之後,才能很好的理解這裡各個attribute的含義.
attribute主要分為三類:
- 讀寫屬性: (readwrite/readonly) 決定是否產生set訪問器
- setter語意 (assign/retain/copy)set訪問器的語義,決定以何種方式對資料成員賦予新值。
- 原子性: (atomic/nonatomic)
readwrite:產生setter\getter方法 (預設)
readonly:只產生getter方法.
此標記說明屬性是唯讀,如果你指定了readonly,在@implementation中只需要一個getter。或者如果你使用@synthesize關鍵字,也只會產生getter方法。如果你試圖使用點操作符為屬性賦值,你將得到一個編譯錯誤。readonly關鍵字代表setter不會被產生, 所以它不可以和 copy/retain/assign組合使用。
assign:簡單賦值,不更改索引計數
此標記說明設定器直接進行賦值,這也是預設值。在使用垃圾收集的應用程式中,如果你要一個屬性使用assign,且這個類符合NSCopying協議,你就要明確指出這個標記,而不是簡單地使用預設值,否則的話,你將得到一個編譯警告。這再次向編譯器說明你確實需要賦值,即使它是可拷貝的。
retain:釋放舊的對象,將舊對象的值賦予輸入對象,再增加輸入對象的索引計數為1
指定retain會在賦值時喚醒傳入值的retain訊息。此屬性只能用於Objective-C物件類型,而不能用於Core Foundation對象。(原因很明顯,retain會增加對象的引用計數,而基礎資料型別 (Elementary Data Type)或者Core Foundation對象都沒有引用計數)。
copy:建立一個索引計數為1的對象,然後釋放舊對象
它指出,在賦值時使用傳入值的一份拷貝。拷貝工作由copy方法執行,此屬性只對那些實行了NSCopying協議的物件類型有效。更深入的討論,請參考“複製”部分。
atomic/nonatomic:
指出訪問器不是原子操作,atomic表示屬性是原子的,支援多線程並發訪問,而預設地nonatomic,訪問器是原子操作。這也就是說,在多線程環境下,解析的訪問器提供一個對屬性的安全訪問,從擷取器得到的傳回值或者通過設定器設定的值可以一次完成,即便是別的線程也正在對其進行訪問。如果你不指定nonatomic,在自己管理記憶體的環境中,解析的訪問器保留並自動釋放返回的值,如果指定了nonatomic,那麼訪問器只是簡單地返回這個值。沒有特別的多線程要求建議用 nonatomic 有助於提高效能。
在iOS5引入了自動引用計算(ARC)之後,物件變數屬性新增了strong和weak,strong與retain作用類似,可以說是用來代替retain.
存取修飾詞
Objective-C提供了3條指令來控制對一個對象的執行個體變數的訪問:
@protected: 用此指令修飾的執行個體變數可以被該類和任何子類定的方法直接存取,這是預設情況。
@private:用此指令修飾的執行個體變數可以被定義在該類的方法直接存取,但是不能被子類中定義的方法直接存取。
@public:用此指令修飾的執行個體變數可以被該類中的方法直接存取,也可以被其它類定義的方法直接存取。
@package 關鍵字是在Mac 10.5 Objective-C runtime中新添加的,用以支援64-bit系統。
@package
is a new instance variable protection class, like @public
and @protected
. @package
instance variables behave as follows:
@public
in 32-bit;
@public
in 64-bit, inside the framework that defined the class;
@private
in 64-bit, outside the framework that defined the class.
In 64-bit, the instance variable symbol for an @package
ivar is not exported, so any attempt to use the ivar from outside the framework that defined the class will fail with a link error.
Objective-C入門教程03:屬性(@property和@synthesize)