此文概括介紹了 Objective-C 語言中的基本元素粱挡。其范圍僅限于 Objective-C 語言對 ANSI C 的擴(kuò)展赠幕,而沒有介紹 C 語言的基礎(chǔ)元素,因?yàn)榻榻B這方面的資料已經(jīng)有很多了询筏。
A.1 變量
在 Objective-C 中榕堰,變量名的詞法規(guī)則與 ANSI C 中變量名的詞法規(guī)則相同,即變量名由字母嫌套、下劃線或數(shù)字(1~9)的組合組成逆屡,但第一字符不能是數(shù)字,而且區(qū)分大小寫踱讨。
A.1.1 Objective-C 保留字
在一門編程語言中魏蔗,保留字(reserved word)是指在該語言中具有特殊意義的符號,因此它不能用作變量的名稱痹筛。在 ANSI C 相比的基礎(chǔ)上莺治,Objective-C 增加了許多保留字,如表A-1所示:
表A-1 不能用作變量名的 Objective-C 保留字
_Bool | _cmd | _Complex | _Imaginary | atomic |
---|---|---|---|---|
bycopy | byref | BOOL | Class | id |
IMP | inline | inout | instancetype | out |
NO | nonatomic | NULL | SEL | self |
Protocol | restrict | retain | Class | id |
super | YES |
A.1.2 變量的范圍
變量的可見性和可訪問性與其范圍有關(guān)帚稠。變量可以存在于語句塊谣旁、函數(shù)、方法滋早、對象實(shí)例(或關(guān)聯(lián)起來的對象)蔓挖、單個(gè)文件和多個(gè)文件中。ANSI C 定義了以下4種變量范圍馆衔。
- 塊: 在語句塊中聲明的變量擁有塊范圍瘟判。在語句塊中聲明的變量只能在這個(gè)語句塊中可見和被訪問。
- 文件:擁有文件范圍的變量只能在聲明它的文件中可見和被訪問角溃。
- 函數(shù):在函數(shù)/方法中聲明的變量擁有函數(shù)范圍拷获。這些變量只能在相關(guān)函數(shù)/方法中可見和被訪問。
- 函數(shù)原型:在函數(shù)/方法原型的參數(shù)列表中定義的變量擁有函數(shù)原型范圍减细。這些變量可以在相關(guān)函數(shù)/方法中可見和被訪問匆瓜。
訪問修飾符
Objective-C 增加一系列訪問修飾符指令,使用這些指令可以更精細(xì)地控制對實(shí)例變量的訪問未蝌。
Objective-C 定義了多條編譯指令驮吱,使用這些指令可以控制實(shí)例變量的范圍,即在程序中控制變量的可見性萧吠。
- @private: 實(shí)例變量只能在聲明它的類和該類的其他實(shí)例中被訪問左冬。
- @protected: 實(shí)例變量可以在聲明它的類和該類子類的其他實(shí)例方法中被訪問。如果沒有為實(shí)例變量指定保護(hù)級別纸型,這是默認(rèn)的變量范圍拇砰。
- @public: 可以在任何位置訪問實(shí)例變量梅忌。
- @package: 可在通過任何類實(shí)例和函數(shù)訪問實(shí)例變量,但在包之外除破,實(shí)例變量會被當(dāng)成私有變量牧氮。該范圍可用于庫和框架中的類。
這些指令稱為訪問修飾符瑰枫,用于修飾在實(shí)例變量聲明語句塊中聲明的實(shí)例變量踱葛。代碼清單A-1展示了類實(shí)例變量的聲明語句,這段代碼聲明了一個(gè)可在任何位置訪問的變量(int型變量counter)光坝、一個(gè)只能在聲明它的類及該類的子類中訪問的變量(float型變量temperature)尸诽,以及一個(gè)只能在聲明它的類中訪問的變量(NSString *型變量descripton)。
代碼清單A-1 使用訪問修飾符聲明實(shí)例變量
{
@public int counter;
@protected float temperature;
@private NSString *description;
}
A.2 數(shù)據(jù)類型
因?yàn)?Objective-C 是 C 語言的嚴(yán)格父集教馆,所以它支持所有 ANSI C 數(shù)據(jù)類型和類型限定符逊谋。Objective-C 還定義了許多本語言專用的數(shù)據(jù)型(布爾型、類實(shí)例類型土铺、id類型胶滋、類定義類型、塊類型悲敷、枚舉類型)究恤。下面幾節(jié)詳細(xì)介紹這些內(nèi)容。
A.2.1 布爾型
布爾型是用于存儲布爾值的 Objective-C 數(shù)據(jù)類型后德,它有兩個(gè)值:真值和假值部宿。在 Objective-C 中,這兩個(gè)值被定義為 YES 和 NO瓢湃,而不是 true(1) 和 false(0)理张。為一個(gè)布爾值分配的存儲大小為1字節(jié)。Objective-C 還支持 C99 類型的 _Bool 和 bool绵患,但 BOOL 是 Objetive-C 中首選布爾數(shù)據(jù)類型雾叭。
A.2.2 類實(shí)例類型
類實(shí)例類型代表對象、類和超類(superclass)落蝙。Objective-C 運(yùn)行時(shí)環(huán)境中有多種類實(shí)例類型织狐,其中最常用的是 id 類型。
1. id類型
id 類型是所有 Objective-C 對象指針的根類型筏勒,用于存儲對任何 Objective-C 對象(不論哪種類型)的引用移迫。下面的語句聲明了一個(gè)類型?為 id、名為 myObject 的變量管行。
id myObject; // 該變量的實(shí)例化對象可以是任何類型
Objective-C 的 id 類型在程序運(yùn)行時(shí)等價(jià)于一種 C 語言結(jié)構(gòu)厨埋,該結(jié)構(gòu)被定義為指向類型定義結(jié)構(gòu) objc_object 的指針,如代碼清單A-2所示病瞳。
代碼清單A-2 id 類型的定義
typedef struct objc_object
{
Class isa;
} *id;
換言之揽咕,id 僅是一個(gè)指向含有 objc_object 標(biāo)識符的 C 語言結(jié)構(gòu)的指針悲酷。
2. instancetype 關(guān)鍵字
instancetype是一個(gè)上下文關(guān)鍵字套菜,可用作方法結(jié)果的數(shù)據(jù)類型亲善,它表明方法返回了相關(guān)結(jié)果類型。方法返回相關(guān)結(jié)果類型是指方法返回接收對象所屬類的實(shí)例逗柴。通過相關(guān)結(jié)果類型可以推斷出下列方法類型:
- 以 alloc 或 new 開頭的類方法蛹头;
- 以 autorelease、init戏溺、retain 或 self 開頭的實(shí)例方法渣蜗。
下面語句使用關(guān)鍵字 new 創(chuàng)建了一個(gè) OrderItem 對象。
OrderItem *item = [OrderItem new];
盡管 NSObject 類的 new 方法將 id 設(shè)置為返回類型旷祸,但編譯器會根據(jù)名為 item 的接收對象所屬的類,推斷正確的結(jié)果類型(本例中為 OrderItem *)。
instancetype 關(guān)鍵字可用于明確指明腕巡,方法返回的是相關(guān)結(jié)果類型顶瞒。代碼清單A-3展示了 OrderItem 類的一個(gè)例子,該類的接口定義了一個(gè)返回相關(guān)結(jié)果類型的方法闰围。
代碼清單A-3 使用 instancetype 關(guān)鍵字返回相關(guān)結(jié)果類型的值
@interface OrderItem : NSObject
+ (instancetype)orderItemWithDescription:(NSString *)description
price:(float)cost;
@end
A.2.3 類定義類型
類定義類型定義了 Objective-C 運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)赃绊。它們包括 SEL、IMP羡榴、Class碧查、objc_object類型。
1. SEL 類型
SEL 類型代表方法選擇器校仑,是一種在 Objective-C 運(yùn)行時(shí)環(huán)境中代表方法名稱的數(shù)據(jù)類型忠售。使用編譯器指令 @selector,可以為名為 helloworld 的方法選擇器創(chuàng)建 SEL 類型的變量:
SEL myHelloMethod = @selector(helloWorld);
該選擇器可用于調(diào)用對象中的 helloWorld 方法迄沫。
2. IMP 類型
IMP 類型代表一種方法指針稻扬,這種指針指向?qū)崿F(xiàn)方法的函數(shù)的內(nèi)存起始地址。下面是定義 IMP 的類型的語法:
typedeff id (*IMP)(id, SEL, ...);
如這個(gè)類型定義所示邢滑,被 IMP 類型指向的函數(shù)接收一個(gè) id 類型腐螟、一個(gè)方法選擇器(SEL)和可變參數(shù)(由可變參數(shù)符號...代表)作為參數(shù),并返回 id 類型的結(jié)果困后。
3. Class 類型
Class 類型代表 Objective-C 類實(shí)例(即對象)乐纸,由各種數(shù)據(jù)元素構(gòu)成。下面是定義 Class 數(shù)據(jù)類型的語法:
typedef struct objc_class *Class;
如這個(gè)類型定義所示摇予,Class 數(shù)據(jù)類型是一種指針汽绢,這種指針指向帶 objc_class 標(biāo)識符的不透明類型。objc_class 結(jié)構(gòu)的成員只能由專門定義的函數(shù)(尤其是使用 Objective-C 運(yùn)行時(shí)庫函數(shù))訪問侧戴。
4. objc_object 類型
Objective-C 對象擁有相應(yīng)的運(yùn)行時(shí)數(shù)據(jù)類型宁昭。當(dāng)編譯器解析 Objective-C 對象的代碼時(shí)跌宛,會生成創(chuàng)建運(yùn)行時(shí)對象類型的代碼,即 objc_object 類型积仗。如代碼清單A-4所示疆拘, 這種數(shù)據(jù)類型是一種帶 objc_object標(biāo)識符的 C 語言結(jié)構(gòu)。
代碼清單A-4 objc_object
struct objc_object
{
Class isa;
/* ...含有實(shí)例變量值的可變長度數(shù)據(jù)... */
}
objc_object類型含有一個(gè)變量寂曹,該變量的類型為 Class哎迄、名稱為 isa;換言之隆圆,它是一個(gè)指向 objc_class 類型變量的指針漱挚。
A.2.4 塊類型
塊提供了創(chuàng)建一組語句(即語句塊)并將其賦予變量(以便在將來調(diào)用)的方式。塊類似于 C 語言的標(biāo)準(zhǔn)函數(shù)渺氧,但塊除了是可執(zhí)行代碼外旨涝,還含有與堆內(nèi)存或棧內(nèi)存綁定的變量。塊是一種 Objective-C 對象(類型為塊)侣背,而且與所有 Objective-C 對象一樣白华,它也是通過指針被訪問的。像處理 Objective-C 對象一樣秃踩,使用 id 類型可以引用塊對象衬鱼。下面的語句聲明了一個(gè)名為 incrementSum 的塊類型變量,該變量擁有一個(gè)類型為 int 的參數(shù)并且不會返回任何值憔杨。
void (^incrementSum)(int);
可以使用存儲修飾符 __block 創(chuàng)建塊變量鸟赫。它可以應(yīng)用于同一詞法范圍內(nèi)、塊常量外部的變量消别,并使用該變量能夠在這個(gè)塊常量中修改抛蚤。該存儲修飾符無法與本地存儲修飾符 auto、register 和 static 應(yīng)用于同一個(gè)變量寻狂。代碼清單A-5給出了 __block 存儲修飾符的用法岁经。
代碼清單A-5 __block 存儲修飾符的用法
__block int totalSum = 0;
void (^incrementSum)(int) = ^(int amount) {
totalSum += amount;
NSLog(@"Current total = %d", totalSum);
};
incrementSum(5);
執(zhí)行代碼清單A-5所示代碼,會輸出如下結(jié)果蛇券;
Current total = 5
因此缀壤,塊變量 totalSum 被初始化為0,然后在調(diào)用該塊常量時(shí)被修改纠亚。
A.2.5 枚舉類型
Objective-C 支持標(biāo)準(zhǔn)的 C 語言枚舉類型塘慕,并且為指定枚舉的類型提供了支持。枚舉類型由使用關(guān)鍵 enum 定義的一系列已命名值(也稱為“枚舉器”)構(gòu)成蒂胞。被聲明為枚舉型的變量可以被賦予任何枚舉器值图呢。代碼清單A-6定義了含有一組值的枚舉型變量,該變量的名稱為 color,含有 Red蛤织、Green 和 Blue 值赴叹。
代碼清單A-6 枚舉型定義示例
enum
{
Red,
Green,
Blue,
} color;
枚舉器的默認(rèn)類型為 int。Objective-C 支持顯示地設(shè)置枚舉的類型指蚜,這也稱為“含有固定基礎(chǔ)類型的枚舉類型”乞巧。枚舉支持的基礎(chǔ)類型是帶符號或不帶符號的整型(char、short姚炕、int摊欠、long)丢烘。類型應(yīng)該在 enum 關(guān)鍵字之后指定柱宦,而且前面要加冒號(:)。代碼清單A-7所示的代碼定義了一個(gè)枚舉型變量播瞳,它的名稱為 color掸刊,含有一個(gè)組類型為 unsigned char 的值:Red、Greed赢乓、Blue忧侧。
代碼清單A-7 含有固定基礎(chǔ)類型的枚舉類型
enum : unsigned char
{
Red,
Green,
Blue,
} color;
通常,可使用類型定義聲明枚舉類型牌芋。代碼清單A-8所示的代碼使用類型定義聲明了一個(gè)枚舉型變量蚓炬,該變量的名稱為 color,含有一組類型為 unsigned char 的值:Red躺屁、Greed肯夏、Blue。
代碼清單A-8 含有固定基礎(chǔ)類型的枚舉類型定義
typedef enum : unsigned char
{
Red,
Green,
Blue,
} ColorType;
ColorType color;
在 Objective-C 中犀暑,定義枚舉型值的首選方式是用 NS_ENUM 宏驯击。該宏提供一種約定機(jī)制來聲明枚舉值的基礎(chǔ)類型,并使用一條語句定義新的枚舉類型耐亏。代碼清單A-9使用 NS_ENUM 宏定義了代碼清單A-8中定義的枚舉類型徊都。
代碼清單A-9 使用 NS_ENUM 宏定義枚舉類型
typedef NS_ENUM(unsigned char, ColorType)
{
Red,
Green,
Blue,
};
如代碼清單A-9所示,這個(gè)宏的第一個(gè)參數(shù)是基礎(chǔ)類型广辰,而它的第二個(gè)參數(shù)是新枚舉類型的名稱暇矫。像普通塊語句一樣,這些值會存儲在語句塊中择吊。
A.3 操作符
Objective-C 支持 ANSI C 定義的操作符李根,尤其是下面這些操作符:
- 賦值操作符
- 算術(shù)操作符
- 復(fù)合賦值操作符
- 增量和減量操作符
- 邏輯比較操作符
- 邏輯判斷操作符
- 逐位運(yùn)算操作符
- 復(fù)合逐位運(yùn)算操作符
- 三元運(yùn)算操作符
- 類型轉(zhuǎn)換操作符
- sizeof操作符
- 地址操作符(&)
- 間接操作符(*)
- 逗號操作符
要詳細(xì)了解這些算術(shù)轉(zhuǎn)換法則以及這些操作符的優(yōu)先等級和關(guān)系,請參閱 ANSI C 的規(guī)定干发。
脫字操作符(^)用于處理塊對象朱巨,特別是聲明塊對象類型和定義塊常量。
A.4 語句
Objective-C 支持 ANSI C 定義的條件枉长、循環(huán)和跳轉(zhuǎn)語句冀续,尤其是下面這些語句:
- 條件語句(if琼讽、if else、if else if洪唐、switch)
- 循環(huán)語句(for钻蹬、while、do while)
- 跳轉(zhuǎn)語句(return凭需、goto问欠、break、continue)
A.5 類元素
Objective-C 中的類由多個(gè)結(jié)構(gòu)化元素構(gòu)成粒蜈,這些元素通常分為幾個(gè)部分顺献。本節(jié)概括介紹這些基本類元素。
A.5.1 實(shí)例變量
實(shí)例變量是為類聲明的變量枯怖,用于在類實(shí)例的生命周期中保存實(shí)例的值注整。實(shí)例變量會在對象被初次創(chuàng)建時(shí)被分配內(nèi)存,并在對象被釋放時(shí)被釋放內(nèi)存度硝。實(shí)例變量擁有與對象對應(yīng)的默認(rèn)作用范圍和命名空間肿轨。可以在類接口蕊程、類實(shí)現(xiàn)文件或類擴(kuò)展的實(shí)例變量聲明語句塊中聲明實(shí)例變量椒袍。實(shí)例變量的聲明語句塊必須緊跟相應(yīng)的接口、實(shí)現(xiàn)文件和類擴(kuò)展聲明語句藻茂。代碼清單A-10展示了聲明 Hello 類實(shí)例變量的例子驹暑。
代碼清單A-10 Hello類實(shí)現(xiàn)文件中聲明實(shí)例變量的語句塊
@implementation Hello
{
// 在此處聲明實(shí)例變量
...
}
...
@end
建議在類的實(shí)現(xiàn)文件(而不是公共的類接口)中聲明實(shí)例變量。通常應(yīng)在類實(shí)現(xiàn)文件專用的變量擴(kuò)展中聲明實(shí)例變量捌治。
實(shí)例變量的所有權(quán)限定符
Objective-C 所有權(quán)限定符是一種只能應(yīng)用于可保留對象指針的類型限定符岗钩。要設(shè)置變量的所有權(quán)規(guī)則,應(yīng)在變量聲明中將所有權(quán)限定符放置在對象指針類型之前肖油。表A-2列出了4個(gè)所有權(quán)限定符兼吓。
限定符 | 描述 |
---|---|
__autoreleasing | 當(dāng)變量被賦予新值時(shí),新值會被保留和自動釋放森枪,而舊值會被發(fā)送釋放消息 |
__weak | 變量使用簡單賦值操作(即不復(fù)制或保留輸入值)视搏。如果對象被釋放了,相應(yīng)的變量值會被設(shè)置為nil |
__unsafe_unretained | 變量使用簡單賦值操作(即不復(fù)制或保留輸入值) |
__strong | 當(dāng)變量被賦予新值時(shí)县袱,新值會被保留浑娜,而舊值會被發(fā)送釋放消息 |
默認(rèn)的所有權(quán)限定符為__strong(在沒有明確設(shè)置限定符的情況下)。下面語句聲明了一個(gè)名為hello的變量(類型為 Hello *)式散,其所有權(quán)限定符為 __weak筋遭。
__weak Hello *hello;
A.5.2 屬性
在 Objective-C 中,屬性通過訪問方法(即獲取方法和設(shè)置方法),為訪問對象的共享狀態(tài)提供了一種便利機(jī)制漓滔。屬性與實(shí)例變量的區(qū)別在于编饺,屬性不直接訪問對象的內(nèi)部狀態(tài)。在處理 Objective-C 屬性時(shí)响驴,編譯器可以根據(jù)你提供的規(guī)格自動生成訪問方法透且。
可以使用 @property 關(guān)鍵字聲明屬性,后跟一系列可選特性(封閉在圓括號內(nèi))豁鲤、屬性類型和屬性名稱秽誊。
@property (特性) 類型 屬性名稱;
屬性聲明特性用于設(shè)置存儲語義和其他屬性行為。表A-3列出了可用的屬性特性琳骡。
表A-3 屬性的特性
屬性 | 描述 | 注釋 |
---|---|---|
readwrite | 必選 | 訪問限定符锅论。默認(rèn)設(shè)置 |
readonly | 必選 | 訪問限定符。無法同時(shí)選擇 readwrite 和 readonly |
assign | 使設(shè)置方法使用簡單賦值操作(即不復(fù)制或保留輸入值) | 所有權(quán)限定符日熬。在手動內(nèi)存管理方式(MRR)中使用棍厌。MRR 中的默認(rèn)值 |
weak | 使設(shè)置方法使用簡單賦值操作。如果屬性實(shí)例被釋放了竖席,那么支持屬性的實(shí)例變量會被設(shè)置為 nil | 所有權(quán)限定符。在 ARC 內(nèi)存管理方式中使用 |
unsafe_unretained | 使設(shè)置方法使用簡單賦值操作 | 所有權(quán)限定符敬肚。在 ARC 內(nèi)存管理方式中使用 |
copy | 在使用設(shè)置方法賦值時(shí)毕荐,調(diào)用復(fù)制方法并向舊值發(fā)送釋放信息 | 所有權(quán)限定符 |
retain | 在設(shè)置方法中,舊值會被發(fā)送釋放消息艳馒,而屬性會使用保留賦值操作 | 所有權(quán)限定符憎亚。與強(qiáng)引用特性類似(在手動內(nèi)存管理方式中使用) |
strong | 在設(shè)置方法中,舊值會被釋放消息弄慰,而屬性會使用保留賦值操作 | 在 ARC 內(nèi)存管理方式中使用的所有權(quán)限定符第美。ARC 中的默認(rèn)設(shè)置 |
getter=getterName | 使用“獲取方法的名稱”指定獲取方法的名稱 | ---- |
setter=setterName | 使用“設(shè)置方法的名稱”指定設(shè)置方法的名稱 | ---- |
nonatomic | 將屬性的訪問方法設(shè)置為非自動生成(默認(rèn)設(shè)置)。nonatomic 屬性擁有更好的性能陆爽,但無法保證當(dāng)多個(gè)線程訪問屬性時(shí)什往,能夠通過屬性訪問方法返回具有線程安全性的值 | ---- |
屬性定義是在類的實(shí)現(xiàn)文件中實(shí)現(xiàn)的。在大多數(shù)情況下慌闭,屬性是由實(shí)例變量支持的别威,因此屬性定義包括定義屬性的獲取方法和設(shè)置方法、聲明實(shí)例變量以及在獲取/設(shè)置方法中使用這些實(shí)例變量驴剔。 Objective-C 提供了3種定義屬性的方式:顯示定義省古、通過關(guān)鍵字補(bǔ)全和自動補(bǔ)全。
A.5.3 方法
Objective-C 既支持實(shí)例方法丧失,也支持類方法豺妓。實(shí)例方法是指在類實(shí)例(對象)中調(diào)用的方法,因此,實(shí)例方法可以直接訪問對象的實(shí)例變量琳拭。類方法是指在類中調(diào)用的方法载佳。可以在類的接口臀栈、協(xié)議和類別(category)中聲明方法蔫慧。因此,應(yīng)在相應(yīng)的類/類別的實(shí)現(xiàn)文件中定義已聲明的類权薯。
方法的聲明設(shè)置了方法的類型姑躲、返回值的類型、方法的名稱盟蚣、方法的參數(shù)和相應(yīng)的參數(shù)類型黍析。方法的類型標(biāo)識符指明了該方法是類方法還是實(shí)例方法。類方法的聲明中含有一個(gè)加號(+)屎开,它表明方法的作用范圍為類阐枣,這意味著方法作用類一級,無法訪問類中的實(shí)例變量(除非將它們作為參數(shù)傳遞給方法)奄抽。實(shí)例方法的聲明中含有一個(gè)減號(-)蔼两,它表明這些方法的作用范圍為對象。這意味著這些方法作用于對象一級逞度,而且可以直接訪問對象及其父對象中的實(shí)例變量(在遵守這些實(shí)例變量訪問控制規(guī)定的情況下)额划。
方法的名稱中含有參數(shù)和冒號。每個(gè)參數(shù)的類型都是在圓括號中設(shè)置的档泽,后跟方法原型參數(shù)俊戳。參數(shù)的名稱和類型由冒號分隔,如下例所示:
-(void)incrementSum:(int)value;
該方法的名稱為 incrementSum:馆匿,它擁有一個(gè) int 型的參數(shù) value抑胎。如果方法含有多個(gè)參數(shù),就需要多個(gè)名稱-參數(shù)對渐北,如下例所示:
-(int)addAddend1:(int)a1 addend2:(int)a2;
該方法的名稱為 addAddend1:addend2:阿逃,它擁有兩個(gè) int 型的參數(shù) a1 和 a2。
返回類型用于設(shè)置方法返回變量的類型(如果存在返回變量)腔稀。返回類型是在圓括號中設(shè)置的盆昙,后跟方法的類型。如果方法沒有返回值焊虏,那么就應(yīng)將返回類型聲明為 void淡喜。
下面的語句聲明了一個(gè)類方法,它的名稱為 hydrogenWithProthons:neutrons:诵闭,擁有兩個(gè) unsigned int 型的參數(shù) nProtons 和 nNeutrons炼团。
+ (void)hydrogenWithProthons:(unsigned)nProtons neutrons:(unsigned)nNeutrons;
A.5.4 接口
類接口設(shè)置了類的狀態(tài)和行為澎嚣,封裝了實(shí)例變量、屬性和方法瘟芝。類接口的聲明以 @interface 指令和類名稱開頭易桃,以 @end 指令結(jié)束。代碼清單A-11展示了聲明類接口的正式語法锌俱。
代碼清單A-11 類接口的聲明語法
@interface 類的名稱 : 父類的名稱
{
// 實(shí)例變量的聲明
...
}
// 屬性和方法的聲明
...
@end
父類創(chuàng)建了通用接口和實(shí)現(xiàn)代碼晤郑,子類可以繼承、修改和補(bǔ)充這些元素贸宏。Objective-C 中的絕大多數(shù)類都是 NSObject 類的子類造寝,NSObject 類是大多數(shù) Foundation 框架的根類(基類),它提供了 Objective-C 運(yùn)行時(shí)環(huán)境的基礎(chǔ)接口吭练。
提前聲明
使用 @class 指令可以在獲取類的完整規(guī)格前诫龙,在類接口中聲明類。這樣做可以在無須導(dǎo)入相應(yīng)頭文件的情況下鲫咽,告訴編譯器類的存在签赃,從而使編譯器能夠執(zhí)行靜態(tài)類型檢查。提前聲明可用于解決文件之間的循環(huán)依賴問題分尸。
A.5.5 實(shí)現(xiàn)代碼
類的實(shí)現(xiàn)文件通過實(shí)現(xiàn)類的屬性和方法定義了類的行為锦聊。類實(shí)現(xiàn)文件以 @implementation 指令和類的名稱開頭,以 @end 指令結(jié)束寓落。代碼清單A-12展示了聲明類實(shí)現(xiàn)文件的正式語法括丁。
代碼清單A-12 類實(shí)現(xiàn)文件的語法
@implementation 類的名稱
{
// 實(shí)例變量的聲明
...
}
// 屬性和方法的定義
...
@end
在類實(shí)現(xiàn)文件中定義的方法必須直接與相應(yīng)的類接口對應(yīng),例如伶选,代碼清單A-13所示的代碼創(chuàng)建了 Greeting 類的接口和相應(yīng)的實(shí)現(xiàn)代碼。
代碼清單A-13 Greeting類接口和實(shí)現(xiàn)代碼
#import <Foundation/Foundation.h>
@interface Greeting : NSObject
@property (readwrite) NSString *salutation;
-(void)hello:(NSString *)user;
@end
#import "Greeting.h"
@implementation Greeting
-(void)hello:(NSString *)user
{
NSLog(@"%@, %@", self.salutation, user);
}
@end
A.5.6 協(xié)議
協(xié)議規(guī)定了類可以實(shí)現(xiàn)的方法和屬性尖昏。協(xié)議的聲明以 @protocol 指令開頭仰税,后跟協(xié)議的名稱,以 @end 指令結(jié)束抽诉。協(xié)議中含有必選和可選方法陨簇。協(xié)議的實(shí)現(xiàn)代碼無須實(shí)現(xiàn)可選方法。@required 指令和 @optional 指令(后跟一個(gè)或多個(gè)方法名稱)用于設(shè)置必選和可選方法迹淌。如果沒有明確設(shè)置這兩個(gè)關(guān)鍵字中的任何一個(gè)河绽,那么默認(rèn)為使用 @required 指令。代碼清單A-14展示了聲明協(xié)議的語法唉窃。
代碼清單A-14 聲明協(xié)議的語法
@protocol 協(xié)議的名稱
// 屬性的聲明
@required
// 方法的聲明
@optional
// 方法的聲明
@end
通過在尖括號中設(shè)置其他協(xié)議耙饰,可以組合使用協(xié)議,這稱為遵守其他協(xié)議纹份。逗號用于分隔多個(gè)協(xié)議苟跪,如代碼清單A-15所示廷痘。
代碼清單A-15 組合使用多個(gè)協(xié)議
@protocol 協(xié)議的名稱<協(xié)議的名稱>
// 方法的聲明
@end
通過類似的語法可以使用接口遵守多個(gè)協(xié)議,如代碼清單A-16所示件已。
代碼清單A-16 使接口遵守協(xié)議的語法
@interface 類的名稱 : 父類的名稱<協(xié)議的名稱>
// 方法的聲明
@end
通常笋额,類的接口和實(shí)現(xiàn)代碼存儲在不同的文件中,存儲接口的頭文件擁有 .h 后綴篷扩,而實(shí)現(xiàn)文件擁有 .m 后綴兄猩。
A.5.7 類別
通過類別(category)可在不進(jìn)行子類化的情況下,為已經(jīng)存在的類添加功能鉴未。類別中的方法會變成類的組成部分(在程序范圍之內(nèi))枢冤,并且會被該類的所有子類繼承。
類別接口聲明以 @interface 關(guān)鍵字開頭歼狼,后跟已經(jīng)存在的類名稱掏导、由圓括號封裝的類別名稱以及類別遵守的協(xié)議(如果存在),以 @end 關(guān)鍵字結(jié)束羽峰。應(yīng)在這些語句之間添加方法的聲明趟咆。代碼清單A-17展示了聲明類別的語法。
代碼清單A-17 聲明類別的語法
@interface 類的名稱(類別的名稱)
// 方法的聲明
@end
與類的實(shí)現(xiàn)文件相似梅屉,類別在其實(shí)現(xiàn)中定義方法值纱。代碼清單A-18展示了類別實(shí)現(xiàn)的語法:
代碼清單A-18 類別實(shí)現(xiàn)的語法
@implementation 類的名稱(類別的名稱)
// 方法的定義
@end
A.5.8 類擴(kuò)展
可以將類擴(kuò)展為匿名類別。在類擴(kuò)展中聲明的方法必須在相應(yīng)類的實(shí)現(xiàn)文件中實(shí)現(xiàn)坯汤。與類別相反虐唠,類擴(kuò)展可以聲明實(shí)例變量和屬性。代碼清單A-19展示了類擴(kuò)展的語法:
代碼清單A-19 聲明類擴(kuò)展的語法
@interface 類的名稱()
{
// 實(shí)例變量的聲明
}
// 屬性的聲明
// 方法的聲明
@end
通常惰聂,可以將類擴(kuò)展放在類的實(shí)現(xiàn)文件中疆偿,使用它們組織和聲明額外的、必要的私有方法(如不屬于已聲明的公用 API 的方法)搓幌,以單獨(dú)在某個(gè)類中使用杆故。