Foundation庫下的NSString,NSArray, NSDictionary……可以被繼承嗎

前幾日被人提問,Foundation庫下的NSString可以被繼承嗎? 一下子把我問蒙圈了,從來沒有用過呀! 後來自己一用代碼一試。
這裏寫圖片描述

寫了一個繼承於NSString 的類。然後在VC中去初始化。
這裏寫圖片描述

看來了一切是那樣的風平浪靜。但是一運行的時候,浪浪的事發生了
這裏寫圖片描述

直接崩潰了,說找不到這個抽象的方法。但是不應該呀,我繼承了NSString類就應該可以用它裏面的方法呀。

官方文檔有介紹類簇可以看一下寫的很詳細:
[https://developer.apple.com/library/ios/documentation/General/Conceptual/CocoaEncyclopedia/ClassClusters/ClassClusters.html]

下面我就把自己的理解寫下來,類簇就是把一組有共同特性的子類都繼承說一個父類,當我們在需要各個子類的時候,我們就需要去操作父類就可以,運用抽象工廠模式,父類會根據你的需求返回給你相應的子類。比如

NSNumber *aChar = [NSNumber numberWithChar:’a’];
NSNumber *anInt = [NSNumber numberWithInt:1];
NSNumber *aFloat = [NSNumber numberWithFloat:1.0];
NSNumber *aDouble = [NSNumber numberWithDouble:1.0];

我們只需要操作NSNumber就可以得到相應的char,int ,flat,double類性的對象。

但爲什麼會繼承這樣類會崩潰呢?接下來看看另一代碼
這裏寫圖片描述
發現+ alloc後並非生成了我們期望的類實例,而是一個NSPlaceholderString的中間對象,後面的- init或- initWithXXXXX消息都是發送給這個中間對象,再由它做工廠,生成真的對象分別是這裏的NSCFConstantString和NSCFString_類
於是順着思路猜實現,NSPlaceholderString必定用某種方式存儲了它是由誰alloc出來的這個信息,才能在init的時候知道要創建的是可變字符串還是不可變字符串。

這裏還有個現象:
跟蹤[LBString alloc]返回的對象類型爲LBString類,
跟蹤[NSString alloc]返回的對象類型爲NSPlaceholderString,而不是NSString類。。

推斷是 NSString alloc時有個中間層,就是我們上面看到的NSPlaceholderString,alloc的對象先統一爲這個類對象之後,在後面調用 NSPlaceholderString的類方法時,比如initWithFormat:才返回具體的類,即在NSPlaceholderString這一層做個“代理工廠”,根據調用的不同init方法再返回具體的類,比如 NSCFString。
那麼爲什麼我們自己的類調用alloc時,就不返回NSPlaceholderString這個類對象了呢?關鍵就在於NSString alloc方法的實現。NSString的alloc方法實現可以猜測一下:

@class NSPlaceholderString;  
@interface NSString:(NSObject)  
+ (id) alloc;  
@ end  

@implementation NSString  
+(id) alloc {  
    if ([self isEquals:[NSString class]]) {  
        return [NSPlaceholderString alloc];  
    }  
    else  
        return [super alloc];  
}  
@end  

@interface NSPlaceholderString:(NSString)  
@end 

關鍵就在於alloc的實現,可以發現,當只用NSString調用alloc的時候,由於self == [NSString class],所以這時返回的是NSPlaceholderString的類對象;而使用其他類(比如派生類)調用alloc時,返回的是super的 alloc,這裏也就是[NSObject alloc],而NSObject的alloc方法返回的是調用類的類對象,所以在我們用我們自己的LBString就是LBString類的類對象了所以沒有NSString 的一些方法了。

發佈了26 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章