• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

通过appleNSString和NSCFString实现群集模式的行为

用户头像
it1352
帮助1

问题说明

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

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

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

By 谷歌 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.

正确答案

#1

让我们对如何<$ 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

这篇好文章是转载于:编程之路

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 编程之路
  • 本文地址: /reply/detail/tanhcgkgjg
系列文章
更多 icon
同类精品
更多 icon
继续加载