O-C和C的差別以及其自身的特點
Objective-C中有幾種資料型別和C不太一樣:
- - id 是一個指標型別,可以指向任何型別的物件
- - BOOL和char是一樣的,但是做為布林值使用。
-
YES 表示1
NO 表示0 - - IBOutlet 是個沒有任何意義的巨集,可以忽略。當InterfaceBuilder從.h檔案中讀取類定義時,這個巨集會對其做出一個提示。
- - IBAction和void是一樣的,同樣僅用作對Interface Builder的提示。
- - nil和NULL是一樣的,我們使用nil而不用NULL是因為我們用來表示物件的指標為空。
另外
#import和#include是一樣的,但是#import可以確保引用的檔案只被引用一次。
- 目前好象只有Apple使用Objective-C作為其支援的語言吧。
- 與C++的不同之處有:
- O-C中所有的類都必須繼承自NSObject。
- O-C中所有物件都是指標的形式。
- O-C用self代替this。
- O-C使用id代替void*。
- O-C使用nil表示NULL
- O-Ck只支援單繼承。
- O-C使用YES/NO表示TRUE/FALSE
- O-C使用#import代替#include
- O-C中用訊息表示類的方法,並採用[aInstance method:argv]呼叫形式。
- O-C支援反射機制
- O-C支援Dynamic Typing, Dynamic Binding和Dynamic Loading。
- 與C++的相同之處有:
- 與C共享的部分一致。
- 可以使用assert(BOOL), 一般用NSCParameterAssert(BOOL)代替。
- O-C中的命名字首說明:
- NS-:NextStep
- CF-:Core Foundation
- CA-:Core Animation
- CG-:Core Graphics
- UI-:User Interface
- O-C中的訊息特殊性:
- 呼叫訊息的類可以不知道如何響應這個訊息。如果它不知道如何處理這個訊息,它會自動的將這個訊息轉給其他的類,比如它的父類。
- 呼叫訊息的類可以是nil。在C++中,在使用類方法之前,我們都需要檢查物件是否為空,所以在實現解構函式的時候,常會有如下的程式碼,如if(var) { delete var; }
- O-C中的函式宣告格式有:
- -/+ (return type) function_name;
- -/+ (return type) function_name : (parameter type)parameter;
- -/+ (return type) function_name : (parameter type)parameter1 otherParameter :(parameter_type) parameter2
- 以上引數說明:-表示一般函式,+表示靜態函式。otherParameter是引數的別名(第一個引數的別名省略),在函式呼叫時方便指定。
- O-C中的構造/解構函式
- O-C中的init()/release()對應於C++的構造/解構函式。alloc()/dealloc()也就對應於C++的new和delete,其中的dealloc()由於引用計數的自動呼叫而不用手動呼叫。
- O-C中父類的init()/release()函式需要子類的手動呼叫。而且每次都必須呼叫。不同於C++的自動呼叫。
- 建構函式(- (id) init)呼叫形如:CSample* pSample=[CSample alloc]init];其中alloc(+ (id)alloc)是繼承來的static函式,init是繼承來的一般函式,如重寫一般函式時,則相當於C++的覆蓋(不帶引數)或過載(帶引數)。
- 解構函式(- (void) release)將引用計數減1,當=0時父類的release()會自動呼叫dealloc(-(void) dealloc);
- 當O-C沒有資料成員時,可省略{},建議保留。
- 繼承下來的方法,如:-(id) init可以標頭檔案中省略,建議保留
- 0-C中只有資料成員的訪問限制,沒有方法的訪問限制。
- 同C++一樣,資料成員有三種訪問限制public, protected,private,預設是protected。
示例:1 2 3 4 5 6 7 8 9 @interface AccessExample: NSObject {
@public
intpublicVar;
@protected
intprotectedVar;
@private
intprivateVar;
}
@end
- 方法的訪問限制可通過Category實現
示例:1 2 3 4 5 6 7 8 9 @interface MyClass
-(void) sayHello {
NSLog(@"Hello");
}
@end
@interface MyClass(Private)
-(void) kissGoodbye;
@end
- 同C++一樣,資料成員有三種訪問限制public, protected,private,預設是protected。
- O-C中沒有類的靜態變數,只有全域性變數
- O-C中的陣列NSArray可以儲存不同型別的資料。
- O-C也支援run-time時的類型別檢查
- - (BOOL) isKindOfClass: classObj
用於判斷該物件是否屬於某個類或者它的子類 - - (BOOL) isMemberOfClass: classObj
用於判斷該物件是否屬於某個類(這裡不包括子類) - - (BOOL) respondsToSelector: selector
用於判斷該物件是否能響應某個訊息。這裡,我們可以將@selector後面帶的引數理解為C++中的函式指標。
注意:
1)不要忘了@
2)@selector後面用的是(),而不是[]。
3)要在訊息名稱後面跟:,無論這個訊息是否帶引數。如:[pSquarerespondsToSelector:@selector(Set: andHeight:)]。 - + (BOOL) instancesRespondToSelector: selector
用於判斷該類是否能響應某個訊息。這是一個靜態函式。 - -(id) performSelector: selector :呼叫物件的selector方法。
- conformsToProtocol 類似於respondsToSelector,用於動態檢查某個物件是否遵守某個協議。
- - (BOOL) isKindOfClass: classObj
- Category:在沒有原始碼的情況下,為一個已經存在的類新增一些新的功能
- 只能新增新的方法,不能新增新的資料成員
- Category 的名字必須是唯一的
- Protocol:相當於C++中的純虛類
- 形如:@interface MyDate: NSObject<Printing> { } @end
- 使用:MyDate * dat = [[MyDate alloc] init];id<Printing> var = dat; [varprint]。
- 說明:我們首先聲明瞭Printing 協議,任何遵守這個協議的類,都必須實現print 方法。在Objective C中,我們通過<>來表示遵守某個協議。當某個類宣告要遵守某個協議之後,它就必須在.m檔案中實現這個協議中的所有方法。使用id<Printing> 作為型別,而不是象C++中的Printing*var。
- IBOutlet, IBAction: 這兩個東西其實在語法中沒有太大的作用。如果你希望在InterfaceBuilder中能看到這個控制元件物件,那麼在定義的時候前面加上IBOutlet,在IB裡就能看到這個物件的outlet,如果你希望在Interface Builder裡控制某個物件執行某些動作,就在方法前面加上(IBAction)。
- 儘量避免在一行語句中進行兩層以上的巢狀
- 訊息轉發:- (void) forwardInvocation:(NSInvocation*)anInvocation;
Categories
1 2 3 4 5 6 7 8 |
#import “ClassName.h”
@interface ClassName ( CategoryName )
//method declarations
@end
#import “ClassName+CategoryName.h”
@implementation ClassName ( CategoryName)
//method definitions
@end
|
For example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
@interface MyObject : NSObject{
NSNumber *number;
}
-(NSNumber *)number;
@end
@interface MyObject (Setter)
-(void)setNumber:(NSNumber *)newNumber;
@end
@implementation MyObject
-(NSNumber *)number{
return number;
}
-(void)setNumber(NSNumber *)newNumber{
number = newNumber;
}
@end
|
Protocol
1 2 3 4 5 6 7 8 |
@protocol MyProtocol
-(void)requiredMethod;
@optional
-(void)anOptionalMethod;
-(void)anotherOptionalMethod;
@required
-(void)anotherRequiredMethod;
@end
|
For example
1 2 3 4 5 6 7 8 9 10 |
Inherit multiple protocol. @interface Formatter :NSObject Instance. Protocol *myXMLSupportProtocol [email protected](MyXMLSupport);
Check if methods are declared
if(![receiverconformsToProtocol:@protocol(MyXMLSupport)]){
//Object does not conform to MyXMLSupportprotocol
//If you are expecting receiver to implement methodsdeclared in the
//MyXMLSupport protocol, this is probably anerror
}
-(NSString*)formattingService:(id)anObject;
———————————————————————
|
http://icocoa.cn/ocsection/oc-tips/60-category-vs-protocol
Category
Category提供了一種比繼承(inheritance)更為簡潔的方法來對class進行擴充套件,我們可以為任何已經存在的class新增方法(不包括資料成員)卻不需要訪問該class的實現檔案。
新新增的方法和原有的方法具有同等的地位,可以訪問class的資料成員,並且完全植入到class的繼承體系之中,子類同樣會繼承新新增的方法。利用category對類進行擴充套件可以避免使類的繼承體系過於臃腫,複雜,降低了維護成本。另外,新新增的方法如果和已經存在的方法具有相同的prototype,那麼新新增的方法將會覆蓋已經存在的方法,也就是category使得使得在沒有原始檔時修改已存在class的functionality或者清除bug成為可能,所有該class的物件的行為都將發生變化,這一點是繼承無法達到的。
Category的缺點:
如果一個已經存在的方法被新方法覆蓋,那麼將沒有任何途徑可以對舊方法進行呼叫。這一點和繼承是不同的,子類對父類成員函式重寫(override),但我們依然可以對父類中的被重寫的成員函式進行呼叫。
如果有多個category對同一個class的成員函式進行重寫,那麼具體的行為是未定義。
Category的應用:
對類進行擴充套件或patch。
使用category或(anonymous category)來模擬實現private method。
使用category(informal protocol)來實現delegation,在cocoaframework中就大量使用了category來宣告delegate methods。
利用category把一個龐大的class劃分為小塊兒來分別進行開發,從而將functionality更好的進行劃分,利於維護。