二:Objective-C類與繼承和協議
在前面已經提過了對象的初始化,這里首先講的是變量。
2.1 變量
- 局部變量(內部變量): 局部變量是在方法內作定義說明的,其作用域僅限於方法內,離開方法后使用這種變量是非法的。
-
全局變量(外部變量): 其作用域是整個源程序。說明符是extern。例如:
extern int intX;
如果同一源文件中全局變量與局部變量同名,則在局部變量作用域內,全局變量不起作用。
3. 實例變量:在類中定義的實例變量,可以在各個方法內使用。
4. 靜態變量(static):它是方法內部定義的類似於全局變量,作用域為當前類的所有對象。節省內存,靜態變量之存儲一處,供所有對象共用,可更新,更新后,所有對象訪問更新后的值。
5. auto:這是聲明一個自動局部變量,是方法內部變量的聲明方式,是默認設置,一般省略它。
例如:auto int intX 與 int intX 等效。
6. const: 不可改變的變量。
7. volatile:與const相反,該變量的值會發生改變。
2.2 @property 與 @synthesize
在接口文件(.h)中,用@property來標識屬性(實例變量);在實現文件(.m)中,用@synthesize來標識所聲明的屬性,讓系統自動生成設置方法與獲取方法(getter/setter)。
聲明property的語法為: @property (參數1,參數2) 類型 名字;
其中參數主要分為三類: 讀寫屬性: (readwrite/readonly) setter語意:(assign/retain/copy) 原子性: (atomicity/nonatomic)
各參數意義如下:
readwrite:產生setter\getter方法。
readonly:只產生簡單的getter,沒有setter。
assign:默認類型,setter方法直接賦值,而不進行retain操作。
retain:setter方法對參數進行release舊值,再retain新值。
copy:setter方法進行Copy操作,與retain一樣。
nonatomic:非原子性訪問。如果沒有這個關鍵字,會把self作為一個mutex,從而保證了原子性。
“.”操作只能夠在setters和getters中。
例如:在接口文件中: @property int count;
等效於聲明2個方法:
- (int)count; - (void)setCount:(int)newCount;
實現文件(.m)中: @synthesize count;
等效於在實現文件(.m)中實現2個方法--默認的assign:
- (int)count { return count; } -(void)setCount:(int)newCount { count = newCount; }
2.3異常處理
- @try:可能會拋出異常的代碼塊使用。
- @catch:用於捕捉@語塊中拋出的錯誤,可以用多個@catch語句塊。
- @finish:無論哪種情況都要執行的語句塊。
- @throw:自己拋出一個錯誤。
2.4 基礎框架類
- NSString:字符串類型,沒有攜帶字體和大小的信息,不能改變NSString對象的字符串內容,但可以有很多方法可以由一個字符串產生另一個字符串。如果要改變這個字符串本身,需要用到NSString子類NSMutableString。
- NSDate:代表時間和日期。
- NSNumber:包含一個數值(包含bool)的對象。NSNumber本身不是一個數字,所以不能在算術表達式中使用。
- NSData:序列字節,不可修改。要修改的話需要用到NSData子類NSMutableData。NSData主要用於從網上下載數據(以NSData對象返回數據);把對象存儲在文件中;讀取文件數據(將NSData對象當做緩存區)。
- NSSet:無序的不同對象的集合,不可變,可通過調用方法增加或刪除一個集合來獲得新的NSSet對象。它的子類是NSMutableSet。
- NSDictionary:其鍵值對的無序集合,鍵通常是NSString,值可以是任何一個對象,NSDictionary是定長的,它的變長子類是NSMutableDictionary。
- 屬性列表
- NSObject:每個類都是從NSObject繼承來的,它采用NSObject協議,它實現了與NSCopying、NSMutableCopying和NSCoding 協議相關的方法,詳細分析請看2.5.3的類別、2.5.4的協議部分與源碼NSObject.h。
2.5繼承與協議
2.5.1object-c繼承基礎
- object-c不支持多重繼承,只能單繼承,一個類只能有一個父類。
- 方法重寫:若子類中的方法與父類的某一方法具有相同的方法名、返回類型和參數表,則新方法覆蓋原有方法。
- 方法重載:類中可以創建多個方法,他們具有相同的方法名,但具有不同的參數和不同的定義,調用方法時通過傳遞給他們不同個數和類型的參數來覺定使用哪個方法。 方法名一定相同;方法的參數表必須不同,包括參數的個數和類型,以此區分不同的方法體; 方法的返回類型和修飾符可以相同也可以不同。
- self:一個類中的方法調用同一個類的另一個方法是使用self,代表本身,相當於this。
- super:表示父類,可以使用super訪問父類中被子類隱藏或重寫的方法。
2.5.2 訪問控制
- @protected—Methods defined in the class and any subclasses can directly access the instance variables that follow.This is the default case. 該類和任何的子類中的方法可以直接訪問這樣的變量,這是默認的。
- @private —Methods defined in the class can directly access the instance variables that follow, but subclasses cannot. 該類中的方法可以訪問這樣的變量,但不能被子類定義的方法直接訪問。
- @public —Methods defined in the class and any other classes or modules can di- rectly access the instance variables that follow. 除了自己和子類中的方法外,也可以被其他類或者其他模塊中的方法所訪問。開放性最大,但最好避免使用這個作用域。其他類應該使用getter/setter方法來訪問或設置其他類上的實例變量,確保封裝性。
2.5.3 類別
類別的作用:對已經存在的類的擴展,而又不影響原類的情況,Object-C提供了category動態運行時分配,為類添加新的方法。類的實現將分散到多個不同文件或多個不同框架中。
類別的特點:第一: category不像子類,不能定義新的實例變量。第二:名稱沖突,即類別中的方法與現有的方法重名。當發生名稱沖突時,類別具有更高的優先級。例如:
@interface NSObject (NSCoderMethods) //表示類別的名稱為NSCoderMethods,要擴展的對象為NSObject + (NSInteger)version; + (void)setVersion:(NSInteger)aVersion; - (Class)classForCoder; - (id)replacementObjectForCoder:(NSCoder *)aCoder; - (id)awakeAfterUsingCoder:(NSCoder *)aDecoder; @end
類別標准的語法格式如下:
#import “類名.h” @interface 類名 (類別名)//新方法的聲明 @end #import “類名類別名.h” @implementation 類名 (類別名) //新方法的實現 @end
2.5.4 協議
協議的功能類似於c++中對抽象基類的多重繼承。協議是多個類共享方法的列表。協議中列出的方法在本類中並沒有相應的實現,而是由別的類來實現這些方法。如果一個類要遵守一個協議,該類就必須實現特定協議的所有方法(可選方法除外)。
定義一個協議需要使用@protocol指令,緊跟着是協議名稱,然后是聲明的一些方法,在指令@end之前的所有方法的聲明都是協議的一部分。
協議時可以有靜態函數。
@optional表示可以不選擇實現方法。
@required表示一定要實現的方法。
同時采用多個協議只需要在<>內列出多個協議,並用“.”隔開:
@interface Car :NSObject <NSCopying,NSCoding>。
下面的NSObject.h:每個類都是從NSObject繼承來的,它采用NSObject協議,它實現了與NSCopying、NSMutableCopying和NSCoding 協議相關的方法。
/* NSObject.h */ #import <Foundation/NSObjCRuntime.h> #import <Foundation/NSZone.h> @class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; @class Protocol; /*************** Basic protocols ***************/ @protocol NSObject //NSObject協議 //@protocol是聲明協議的標志。后面的NSObject是協議的名稱 //協議中的方法是每個采用者必須實現的方法,這里有19個方法 - (BOOL)isEqual:(id)object; // 用於對象比較 - (NSUInteger)hash; - (Class)superclass; - (Class)class; - (id)self; - (NSZone *)zone; - (id)performSelector:(SEL)aSelector; - (id)performSelector:(SEL)aSelector withObject:(id)object; - (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2; /* 延遲調用參數提供的方法,參數所需參數用withObject傳入(類似於ActionScript3.0中的setTimeout函數) delay單位:秒 */ - (BOOL)isProxy; - (BOOL)isKindOfClass:(Class)aClass; /* 用於判斷對象是不是參數提供的類型 */ - (BOOL)isMemberOfClass:(Class)aClass; /* 用於判斷對象是不是參數提供的類型*/ - (BOOL)conformsToProtocol:(Protocol *)aProtocol; /* 用於判斷對象是否遵守了參數提供的協議*/ - (BOOL)respondsToSelector:(SEL)aSelector; /* 用於判斷對象是否擁有參數提供的方法*/ - (id)retain; //增加對象的計數器 - (oneway void)release; //減少對象的計數器 - (id)autorelease; //自動減少對象的計數器,但是以推遲的方式來實現 - (NSUInteger)retainCount; //返回一個對象當前的計數器 - (NSString *)description; //允許一個對象返回一個字符串來描述它的內容;這個常用於調試debugging @end //表示結束 @protocol NSCopying //NSCopying協議 - (id)copyWithZone:(NSZone *)zone; //協議中的方法是每個采用者必須實現的方法,這里只有一個方法 @end //表示結束 @protocol NSMutableCopying//NSMutableCopying協議 - (id)mutableCopyWithZone:(NSZone *)zone; @end //表示結束 @protocol NSCoding //NSCoding協議 - (void)encodeWithCoder:(NSCoder *)aCoder; - (id)initWithCoder:(NSCoder *)aDecoder; @end /*********** Base class ***********/ @interface NSObject <NSObject> { //告訴編譯器,NSObject正在遵守NSObject協議 Class isa; } + (void)load; + (void)initialize; - (id)init; //對象的屬性初始化 + (id)new; + (id)allocWithZone:(NSZone *)zone; + (id)alloc; - (void)dealloc; //用於類來釋放對象實例變量並釋放動態內存 - (void)finalize AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; - (id)copy; - (id)mutableCopy; + (id)copyWithZone:(NSZone *)zone; + (id)mutableCopyWithZone:(NSZone *)zone; + (Class)superclass; + (Class)class; + (BOOL)instancesRespondToSelector:(SEL)aSelector; + (BOOL)conformsToProtocol:(Protocol *)protocol; - (IMP)methodForSelector:(SEL)aSelector; + (IMP)instanceMethodForSelector:(SEL)aSelector; - (void)doesNotRecognizeSelector:(SEL)aSelector; - (id)forwardingTargetForSelector:(SEL)aSelector; - (void)forwardInvocation:(NSInvocation *)anInvocation; - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector; + (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)aSelector; + (NSString *)description; + (BOOL)isSubclassOfClass:(Class)aClass AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER; + (BOOL)resolveClassMethod:(SEL)sel AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER; + (BOOL)resolveInstanceMethod:(SEL)sel AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER; @end @interface NSObject (NSCoderMethods) //類別 見2.5.3 + (NSInteger)version; + (void)setVersion:(NSInteger)aVersion; - (Class)classForCoder; - (id)replacementObjectForCoder:(NSCoder *)aCoder; - (id)awakeAfterUsingCoder:(NSCoder *)aDecoder; @end #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) @interface NSObject (NSDeprecatedMethods) + (void)poseAsClass:(Class)aClass DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER #if __OBJC2__ UNAVAILABLE_ATTRIBUTE #endif ; @end #endif #if MAC_OS_X_VERSION_10_6 <= MAC_OS_X_VERSION_MAX_ALLOWED