天天看點

Objective-c官方文檔 怎麼自定義類

通過類别來給已經存在的類添加方法來實作自定義類

如果你需要添加一個方法給一個已經存在的類,也許能增加新的功能使你更容易來在我們的應用裡處理一些事情。最簡單的方法是用類别。

這個文法有點想類的接口描述但是他是沒有繼承類的,相反的要指定類别的名字在括号裡面。

@interface ClassName (categoryName)

@end

一個類别可以被定義在任何的類裡面。甚至你不知道他的實作比如Objective-c的一些已經存在的類。定義在你類别的方法對原始類有效的,對繼承原始類也一樣,。在運作時對于你是類别的方法和原始類的方法是沒有差別的。

聲明類别我們通常是聲明一個單獨的頭檔案和實作檔案當用類别裡的方法的時候導入他的頭檔案就行了。

類别可以被用來聲明執行個體和類方法,但是不合适添加額外的屬性,在類别添加屬性是有效的,但是不能在類别添加額外的執行個體變量,這意味着編譯器不能合成任何執行個體變量,不能合成屬性通路器方法,你可以自己在實作檔案裡寫通路器方法,但是不能跟蹤屬性的值除非他已經存在原始的類裡面。

唯一的方法添加一個屬性帶有新的執行個體變量在一個已經存在的類用類的延展。

避免類别名字的沖突

因為添加類到已經知道的方法,是以應該小心給你的建立的類起名字。

如果這個方法定義在類目的名字和原始類的方法名字一樣,或者同一個類的另一個類目的方法名字相同或者甚至父類。當某個方法在運作時實作的原因,這種行為未定義。如果給自己的類添加類别是沒有這種可能的。但是向已經知道的類添加是有問題的。

舉個例子你想伺服器請求一個資料并且給傳回的字元串進行編碼,你給NSString添加一個類目來做這個事情,當你連結另一個架構的時候也有一個類目有同樣的方法,那麼哪個在運作時候會勝出,哪個顯示未定義。

還有一個問題會出現當一個已經存在的類沒有某種方法你加了一個類目提供這個方法實作,如果api更新了也存在這個方法,這時候意味着你的應用将可能出現沖突。

為了避免這個情況,最好添加方法的字首就像自定義類那時候一樣。

類的内部實作擴充延伸

類目和延展有點類似,但是你可以添加到類是有源代碼的在編譯時候,編譯時候就像類目一樣。定義文法:

@interface ClassName ()

因為沒有名字在括号裡,是以經常延展被稱為匿名類。

不想類目,延展是可以添加屬性執行個體變量的。

@interface MyClass()

@property NSObject *obj;

編譯器會合成相關的通路器方法,以及一個執行個體變量在實作檔案。如果你在延展裡定義了一個方法你必須實作這個方法在實作檔案裡面。添加執行個體變量的執行個體:

@interface myClass ()

    id _someCustomInstanceVariable;

使用延展來隐藏私人資訊

公有類定義了方法是别的類可以和你進行互動。類的延展經常擴充類的公有接口用額外的私有方法和屬性來給他們自己的類使用。例如你可以在接口聲明一個隻讀的屬性,但是你可以在實作檔案聲明一個可讀寫的屬性,目的是使本來可以改變屬性的值,而外部不能改變。

@interface person:NSObject

@property (readonly)NSString *uniqueIdentifier;

- (void)doSomeThing;

這意味着uniqueIdentifier可以被另一個對象改變,如果确實有兩個辨別符怎麼辦呢用doSomeThing再建立一個。

為了使這個類自己能直接改變屬性,我們在類的實作裡面定義延展。如下:

@interface MyCalss ()

@property (readwrite) NSString *uniqueIdentifier;

@implementation MyClass 

這意味着編譯器能合成通路器方法,是以延展的私有方法能改變這個屬性值。

别的類通路這個方法會編譯錯誤的。

考慮其他的方法定制類:

考慮可重用行比如我建立 一個自定義的button就是通過繼承而不是通過以上兩種方式來解決,因為還要導入頭檔案什麼的。

繼續閱讀