前几日被人提问,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 的一些方法了。