如何通过apple(NSString和NSCFString)实现群集模式中的行为 [英] How can i implement the behaviour as in cluster pattern by apple (NSString and NSCFString)

查看:522
本文介绍了如何通过apple(NSString和NSCFString)实现群集模式中的行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只是编写以下代码用于测试目的:

I am simply writing the following code for testing purpose:

NSString *aStr = [[NSString alloc] initWithFormat:@"Foo"];
aStr = [aStr initWithFormat:@"Bar"];//Crashed here

I我收到以下错误:

*** initialization method -initWithFormat:locale:arguments: cannot be sent to an abstract object of class __NSCFString: Create a concrete instance!

如果我写下面的代码发生同样的事情

If i write the following code same thing happen

NSString *aStr = [NSString alloc];
aStr = [aStr initWithFormat:@"Foo"];
aStr = [aStr initWithFormat:@"Bar"]; //Crashed here

通过google我知道 initWithFormat 将返回 NSCFString 对象。
我的问题是如果 NSCFString 是派生类 NSString 那么为什么我不能调用 initWithFormat NSCFString 上的方法。如果可以停止可见性我如何在代码中实现。

By google I come to know that initWithFormat will return the NSCFString Object. My question is if NSCFString is derived class of NSString then why I cannot invoke the initWithFormat method on NSCFString. If it is possible to stop the visibility how can I implement in the code.

推荐答案

让我们对如何<$ c进行一些调查$ c> NSString 类集群在内部工作:

Let's do some investigation on how NSString class cluster works internally:

NSString *factory = [NSString alloc];
NSString *theInstance = [factory initWithString:@"I am constant"];
NSLog(@"factory class: %@, instance class: %@", [factory class], [theInstance class]);

输出为:

factory class: NSPlaceholderString, instance class: __NSCFConstantString

正如你所看到的, alloc 方法返回 NSPlaceholderString 的实例。它是一个工厂类,它实现了在 NSString 中声明的所有 init ... 方法。这些方法返回 NSString 的具体(私有)子类。在此示例中,它返回 __ NSCFConstantString

As you can see, the alloc method returns an instance of NSPlaceholderString. It is a "factory" class which implements all the init... methods declared in NSString. These methods return concrete (private) subclasses of NSString. It returns __NSCFConstantString in this example.

如果您将第一行更改为

NSString *factory = [NSMutableString alloc];

输出将更改为:


NSPlaceholderMutableString,实例类:__ NSCFString

NSPlaceholderMutableString, instance class: __NSCFString

因此,可变和不可变字符串有不同的工厂类,以及这些工厂返回不同的子类。

So there are different factory classes for the mutable and immutable strings, and those factories return different subclasses.

您甚至可以检查iOS运行时标头中私有子类的层次结构:这里这里

You can even check the hierarchy of private subclasses in iOS runtime headers: here and here.

现在让我们看看当我们在 __ NSCFConstantString 的实例上调用 initWithString:时会发生什么。

Now let's see what happens when we call initWithString: on an instance of __NSCFConstantString we just created.

[theInstance initWithString:@"Crash"];

正如您所料 - 它崩溃了。在stacktrace中我们可以看到 - [NSString initWithCharactersNoCopy:length:freeWhenDone:] 方法被调用,抛出异常:

As you expected - it crashes. In the stacktrace we can see that -[NSString initWithCharactersNoCopy:length:freeWhenDone:] method is called, throwing an exception:


'NSInvalidArgumentException',原因:'***初始化方法
-initWithCharactersNoCopy:length:freeWhenDone:无法发送到类__NSCFConstantString的抽象对象:创建具体的
实例!'

'NSInvalidArgumentException', reason: '*** initialization method -initWithCharactersNoCopy:length:freeWhenDone: cannot be sent to an abstract object of class __NSCFConstantString: Create a concrete instance!'

所以我们可以在 NSString 类中猜测这个初始值设定项实际上是一种抽象方法(在Objective-C中没有抽象方法,因此在调用时抛出异常)。

So we can guess that this initializer in NSString class is actually an abstract method (kind of - there aren't abstract methods in Objective-C, so it throws an exception when called).

此方法在工厂类 NSPlaceholderString 中实现。但它在所有具体的子类中都没有 ,所以如果你调用任何 init ... 方法,它将调用 NSString 抛出异常的实现。

This method is implemented in the factory class NSPlaceholderString. But it's not implemented in all the concrete subclasses, so if you call any of the init... methods, it will call the NSString implementation which throws the exception.

让我们把它们放在一起构建 NSString的一小部分类集群。它真的很简单,可能与真正的实现完全不同,但我只想展示这个想法。

Let's put it all together and build a tiny part of the NSString class cluster. It's really simplified and probably totally different than the real implementation, but I just wanted to show the idea.

@interface NSPlaceholderString : NSString
@end

@interface __NSCFConstantString : NSString
@end


@implementation NSString

+ (instancetype)alloc {
    return [[NSPlaceholderString alloc] init];
}

- (instancetype)initWithCharactersNoCopy:(unichar *)characters length:(NSUInteger)length freeWhenDone:(BOOL)freeBuffer {
    [NSException raise:NSInvalidArgumentException format:@" initialization method -initWithCharactersNoCopy:length:freeWhenDone: cannot be sent to an abstract object of class %@: Create a concrete instance!'", [self class]];
    return nil;
}

- (instancetype)initWithString:(NSString *)aString {
//this method has to call the "abstract" initializer somewhere. The real implementation is probably more complex, this single line is here for simplicity
    return [self initWithCharactersNoCopy:[aString UTF8String] length:[aString length] freeWhenDone:YES];       
}

@end

@implementation NSPlaceholderString

- (instancetype)initWithCharactersNoCopy:(unichar *)characters length:(NSUInteger)length freeWhenDone:(BOOL)freeBuffer {
    __NSCFConstantString *concreteClassInstance = ...; // create the concrete instance. 
    return concreteClassInstance;
}

@end

@implementation __NSCFConstantString

//implement all the needed methods here. But do NOT implement initWithCharactersNoCopy:length:freeWhenDone:

@end

这篇关于如何通过apple(NSString和NSCFString)实现群集模式中的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆