文件類型說明:
.h 頭文件,用於定義類、實例變量及類中的方法等定義信息(interface)。
.m 源文件,定義方法體,可實現objce-c和c方法(implementation)。
.mm c++源文件
引用頭文件:
可通過#import關鍵字引入想要使用的頭文件,該關鍵字作用通#include相同,不過import會確保每個文件只會被引用一次。
object-c中類的定義有兩部分:interface和implementation
interface部分包含類的定義以及實例變量和方法。interfache通常定義在.h(頭)文件中;
implementation部分包含方法的實現部分(方法體),implementation通常定義在.m(源)文件中。
1 @interface MyClass : NSObject 2 { 3 int count; 4 id data; 5 NSString* name; 6 } 7 -(id)initWithString:(NSString*)aName; 8 +(MyClass*)createMyClassWithString:(NSString*)aName; 9 @end
在上述代碼中,包含了以下信息:
名為MyClass的類,繼承於Cocoa框架中的NSObject類;
定義了3個成員變量:count、data和name(@protected)
以及聲明了2個方法
實例變量也可以放到源文件中定義,如:
1 // 源文件中的:NSObject為可選,一般情況下不用寫 2 @implenmentation MyClass :NSObject 3 { 4 int count; 5 int data; 6 NSString *name; 7 } 8 9 -(id)initWithString:(NSString*)aName 10 { 11 ... 12 }
但需要注意的是,若成員變量定義在源文件中而非頭文件中,則變量的訪問權限都為@private.
object-c支持強類型和弱類型兩種方式定義一個對象變量:
強類型定義時變量類型即類命,且為指針類型
弱類型定義使用id型定義
1 MyClass *myObject; // 強類型定義 2 id myObject; //弱類型定義
方法的定義和引用:
Object-C中的方法同其它面向對象語言一樣,分兩種方法:實例方法(-)和類方法(+)(靜態方法)。
實例方法需要通過類的實例去調用,而靜態方法可直接通過類名去調用。
1 - (void)insertObject:(id)anObject atIndex:(NSUInter)index;
上述代碼中定義了一個名為"insertObject:atIndex"的實例方法,該方法無返回值,並定義了2個形參,類型分別為id和NSUInter。
在定義一個方法時,也可以不指定參數名,如:
1 // 聲明一個沒有參數名的方法 2 -(int) set: (int) n: (int) d; 3 4 // 方法調用 5 [object set : 4 : 5];
方法的調用:
在Object-C中,調用一個方法叫做發送消息,方法調用語句定義在中括號"[]"中:
1 [myArray insertObject:anObject atIndex:0];
為了避免生成大量的臨時變量,Object-C允許嵌套調用方法,使一個方法的返回值當作另一個方法的參數,如:
1 [[myAppObject theArray] inserObject:[myAppObject objectToInsert] atIndex:0];
成員變量:
默認情況下,Object-C中的成員變量為@protected,可通過@public,@private關鍵字修改成員變量的可見性(只有成員變量擁有這些屬性)。
1 @interface MyObject : NSObject 2 { 3 // 成員變量要定義在大括號中 4 @public int n1; 5 @private int n2; 6 @protected int n3; 7 } 8 ...... 9 @end 10 11 // 通過類實例訪問public的成員變量: 12 MyObject *mo = [[MyObject alloc] init]; 13 mo->n1;
若要訪問受保護的成員變量,需要在類中定義相應的get和set方法,通過類實例調用這些方法來達到訪問或設置這些成員變量的目的。
訪問器 :
在Object-C中,提供了@property和@synthesize兩個關鍵字,通過這兩個關鍵字,可以高效的為每個指定的成員變量設定set方法和get方法,稱為屬性
1 // 頭文件 2 @interface MyObject : NSObject 3 { 4 @property int n1, n2; 5 } 6 ... 7 @end 8 9 // 源碼文件 10 @implementation MyObject 11 12 @synthesize n1, n2; 13 ... 14 @end
在上述代碼中,Object-C會自動創建4個方法:n1、n2、setN1和setN2。
可通過對象實例直接調用這4個方法
MyObject *mo = [[MyObject alloc] init]; int l_n1, l_n2; [mo setN1:4]; [mo setN2:8]; l_n1 = [mo n1]; l_n2 = [mo n2];
Object-C也支持使用"."符號來訪問properties
1 mo.n1 = 5;
這種方式同樣適用於調用方法
變量范圍
Object-C中的變量范圍同C一樣,在{}中定義的變量屬於本地變量,只能在{}中使用,本地變量默認初始化值為nil。同樣方法的傳值方式是傳值引用,但當傳遞對象時是地址引用。
Object-C中也支持靜態變量,通過static關鍵字,如:
1 static int n = 0;
靜態變量默認初始值為0,同C一樣。注:靜態變量同樣只能在定義的范圍內使用。
self變量相當於java中的this。
繼承
Ojbect-C中的繼承同java相同,都是單一繼承關系,要繼承一個類,可寫作:
1 @interface ClassA : NSObject 2 3 @end
其中NSObject類是最頂層類,一般所有類的最終父類都是它。
在子類中可以訪問父類中的非private變量的實例變量和方法(靜態方法和實例方法)。
注:只能訪問非private屬性的成員變量,說明該變量必須定義在interface中(類的聲明中),因為在implementation中聲明的成員變量全部都是private。
在子類中通過super訪問父類中的方法,如:
1 [super init];
NSObject類常用方法:
方法名 | 說明 |
-(BOOL) isKindOfClass: class-object |
Is the object a member of class-object or a descendant? |
-(BOOL) isMemberOfClass: class-object |
Is the object a member of class-object? |
-(BOOL) respondsToSelector: selector |
Can the object respond to the method specified by selector? |
+(BOOL) instancesRespondToSelector: selector |
Can instances of the specified class respond to selector? |
+(BOOL)isSubclassOfClass: class-object |
Is the object a subclass of the specified class? |
-(id) performSelector: selector |
Apply the method specified by selector. |
(id) performSelector: selector withObject: object |
Apply the method specified by selector passing the argument object. |
-(id) performSelector: selector withObject: object1 withObject: object2 |
Apply the method specified by selector with the arguments object1 and object2. |
class-object是一個類對象,通過class方法生成,可通過類名和實例名調用class方法生成,如:
1 [Square class]; // Square 是一個類名 2 [mySquare class]; // mySquare 是一個實例 3 4 // 驗證兩個實例是否屬於同一個類 5 if ([obj1 class] == [obj2 class]) 6 { 7 ... 8 } 9 10 // 驗證myFan是否屬於Fraction,即是否是Fraction的實例 11 [myFan isMemberOfClass: [Fraction class]]
selector是一個SEL類型的變量(C中的函數指針),直接通過@selector生成 ,如:
// 為alloc方法生成一個SEL類型變量 @selector (alloc) @selector (setTo:over:) // 查看Fraction類中是否含有setTo:over方法 // 該方法也去父類中查找 [Fraction instancesRespondToSelector: @selector(setTo:over)];
通過performSelector動態調用函數:
1 @implementation Fraction 2 -(void) setTO:(int) a Over:(int)b 3 { 4 ... 5 } 6 -(void) print 7 { 8 // 通過performSelector方法調用setTo:Over 9 // 傳遞2個整數參數4和5 10 [self performSelector:@selector(setTo:Over) withObject:4 withObject:5] 11 } 12 @end
1 if ([graphicObject respondsToSelector: action] == YES) 2 [graphicObject performSelector: action] 3 else 4 // error handling code here
異常
使用@try和@catch捕獲異常:
1 @try 2 { 3 ... 4 } @catch(NSException *exception) 5 { 6 ... 7 } 8 // 可選的放置一個@finally,該語句無論是否有異常發生,都會執行
編寫類的構造函數
可為一個類編寫多個不同的初始化函數,實例化類時通過指定不同的初始化函數執行不同的初始化操作
1 -(Fraction *) initWith: (int) n over: (int) d { 2 self = [super init]; 3 if (self) 4 [self setTo: n over: d]; 5 return self; 6 }
重寫init方法
1 /* 2 * 注,該方法應該返回id類型, 3 * 而不是指定的類的類型 4 * 如果其它類繼承自該類,初始化子類時候返回的類型就會不正確 5 */ 6 7 -(id) init 8 { 9 return [self initWith:0 over:0]; 10 }
在類外部定義的變量會成為全局變量,在任何類和方法中(包括其它文件)中都可以訪問這個變量。
關鍵字extern可用來在類和方法內部訪問全局變量,同PHP的global類似,但切記:
extern是聲明,而不是定義。
在變量前使用extern關鍵字,並不會為該變量分配內存,僅僅是將該變量標識為全局變量,所以不可以在使用extern定義變量時賦值。
枚舉
Object-C支持枚舉類型,格式為:
1 // 定義枚舉 2 enum flag { false, true }; 3 4 // 聲明兩個枚舉變量,該枚舉變量的值只能是true或false 5 enum flag endOfData, matchFound; 6 7 // 定義枚舉 8 enum direction { up, down, left = 10, right }; 9 10 // 或 11 enum boolean { no = 0, false = 0, yes = 1, true = 1 };