iOS類別和類擴充套件

2021-07-10 04:02:54 字數 3969 閱讀 2242

在ios中,有一種機制可以使使用者在沒有遠嗎的情況下擴充套件類的功能,但不是通過繼承,這就是類別。ios中沒有類似c++中可以定義私有方法和私有變數的關鍵字,要定義私有方法和私有變數,可以用類擴充套件來實現。  

類別

類別在不需要繼承的情況下可以擴充套件類的功能。但類別不能新增類的屬性和私有變數。類別可以用來擴充套件cocoa中類的方法,也可以用來擴充套件使用者自己的類中的方法。當我們檢視系統標頭檔案的時候能發現類似@inte***ce nsmutablearray (n***tendedmutablearray)的類定義,其實這就是類別的定義形式。例如下面的**,定義了乙個nsstring的類別,是用來做base64的編碼和解碼的。  

[cpp] view plaincopy  

@inte***ce nsstring (base64)    

-(nsstring *)encodebase64;    

-(nsstring *)decodebase64;    

@end

類別的定義和類的定義有相似之處,都是用關鍵字@inte***ce和類名來定義,不同之處在於類別的定義是在類名之後不是類所繼承的父類,而是用括號括起來的類別名。@end之前的方法定義和類中方法的定義是一樣的。不過,在類別中,不能定義屬性。類別中的方法與原類中的方法的使用是完全一致的,沒有任何差別。所有nsstring的子類也都能使用類這兩個類別中的方法。  

在使用類別的時候,類別中的方法命名特別重要。

如果類別中的方法名與原類中的方法名重名了,在蘋果開發者文件中的描述是,當方法重名的時候,在執行的時候不知道會呼叫哪個方法。實際上,這個應該是有規則可循的。我建了乙個工程,給nsstring增加了乙個類別,裡面重寫了length和substringfromindex方法。length方法是nsstring的方法,substringfromindex是nsstring的乙個類別裡的方法。當我呼叫者兩個方法時,發現呼叫length的時候返回的是系統的那個呼叫,而不是我自己實現。而當呼叫substringfromindex時,呼叫的則是我實現的方法。於是我推斷當系統類中的方法名與自己定義的類別裡的方法重名時,會呼叫系統的方法名,而當自定義類別中的方法名與系統類別中的方法重名時,會使用自定義類別中的方法的實現。為了驗證這一推斷,我又繼續增加了nsarray的類別來進行測試,測試結果正如我推斷的一樣。即使是這樣,我們也不能確定這個結論就是正確的,還有待進一步的驗證。  

在上面的base64類別中,增加兩個方法  

[cpp] view plaincopy  

-(nsuinteger)length;    

-(nsstring *)substringfromindex:(nsuinteger)from;    

[cpp] view plaincopy  

實現這兩個方法    

[cpp] view plaincopy  

-(nsuinteger)length    

-(nsstring *)substringfromindex:(nsuinteger)from    

在實現這兩個方法的時候,

length方法會有乙個警告

,說這是原類中的方法,而第二個方法卻沒有,因為它是nsstring的乙個類別中的方法。將這兩個方法做自己的實現  

現在來試著呼叫一下  

[cpp] view plaincopy  

nsstring *title = @"標題";    

nslog(@"title length:%d", [title length]);    

nslog(@"sub string from index 1: %@", [title substringfromindex:1]);    

輸出結果是:  

[cpp] view plaincopy  

2013-08-16 00:19:30.678 categorytest[12088:c07] title length:2    

2013-08-16 00:19:30.679 categorytest[12088:c07] sub string from index 1: sub string    

length的結果沒有問題,而substring的方法就是呼叫了咱們實現的類別裡的方法。  

再來看看nsarray的類別定義  

[cpp] view plaincopy  

@inte***ce nsarray (arraytest)    

- (nsuinteger)count;    

- (id)objectatindex:(nsuinteger)index;    

- (id)lastobject;    

@end    

前面兩個方法是nsarray自帶的方法,後面乙個方法是nsarray類別裡的方法,將他們用自己的方式實現  

[cpp] view plaincopy  

@implementation nsarray (arraytest)    

- (nsuinteger)count    

- (id)objectatindex:(nsuinteger)index    

- (id)lastobject    

@end    

現在我們來呼叫一下這幾個方法  

[cpp] view plaincopy  

nsarray *array = [nsarray arraywithobjects:@"object 1", @"object 2", nil];    

nslog(@"array count: %d", [array count]);    

nslog(@"array object at index 0:%@", [array objectatindex:0]);    

nslog(@"array last object:%@", [array lastobject]);    

輸出結果如下:  

[cpp] view plaincopy  

2013-08-16 00:19:30.680 categorytest[12088:c07] array count: 2    

2013-08-16 00:19:30.681 categorytest[12088:c07] array object at index 0:object 1    

2013-08-16 00:19:30.681 categorytest[12088:c07] array last object:object 1    

上面的推斷是基於實現的是系統類的類別,如果是自己的類的類別呢,是不是也跟系統的一樣。經過測試,結果稍有不同。當類別中的方法名與類中的方法重名時,呼叫的是類別中的方法。如果多個類別中有相同的方法,這個就跟類別的編譯順序有關了,誰最後編譯就呼叫誰的方法。我試著改變過不同類別檔案的編譯順序,發現方法的呼叫也跟著變了。這個自己可以寫個類測試一下。  

類擴充套件

類擴充套件跟類別的定義有點像,類擴充套件有點像無名的類別。如下定義  

[cpp] view plaincopy  

@inte***ce person ()    

@property (nonatomic, strong) nsstring *address;    

@end

上面的**是定義了乙個person類的類擴充套件,它與類別的不同之處在於,括號裡不需要寫名字。同時也可以在類擴充套件中定義屬性以及私有變數。另乙個不同之處在於,類擴充套件必須與類定義以及類的實現同時編譯,也就是說,類擴充套件只能針對自定義的類,不能給系統類增加類擴充套件。類擴充套件定義的方法必須在類的實現中進行實現。如果單獨定義類擴充套件的檔案並且只定義屬性的話,也需要將類實現檔案中包含進類擴充套件檔案,否則會找不到屬性的set和get方法。

在person的類實現person.m中,需要將person_persionextension.h包含進行,否則是無法使用address屬性的,測試的時候會崩潰,因為找不到setaddress方法。包含之後就一切正常了。 

ios 類別和類擴充套件

二兩種字典轉模型的 本文分為兩部分 一 教你怎樣一部獲取成員屬性 通過nsobject autologproperty分類 二 對比kvc和runtime兩種字典轉模型的方法並抽取乙個分類 void createpropertycodewithdict nsdictionary dict else ...

ios 類別和擴充套件

類別 inte ce classname categoryname methoddeclarations end 注意事項 1 類別是類的擴充套件,只可以宣告方法,不可以宣告變數。並且,類別的方法優先順序較高,可覆蓋原類方法。2 類別的方法中,不可以呼叫super方法。類別的侷限 3 categor...

ios 類別和擴充套件

類別 inte ce classname categoryname methoddeclarations end 注意事項 1 類別是類的擴充套件,只可以宣告方法,不可以宣告變數。並且,類別的方法優先順序較高,可覆蓋原類方法。2 類別的方法中,不可以呼叫super方法。類別的侷限 3 categor...