0

我从 llvm 源代码中注意到编译器支持该标志:

-fconstant-string-class=CLASSNAME

如果此标志不存在,编译器似乎默认为 NSConstantString。

在检查 Apple 的 Foundation Library 后,NSConstantString 继承自 NSSimpleCString,后者提供了启用 ObjC 常量字符串行为所需的 ivars。这又是 NSString 的子类。

但是,在普通的 ObjC 代码中,以下内容是完全合法的:

NSString *anNSString = @"This is an NSConstantString?";

这似乎很好(NSConstantString 是子类),除了:

1) 常量字符串的数据应该汇集到 NSSimpleCString 中声明的 ivars 中,这对 NSString 是不可用的。

2) NSString 的迭代方法表明它是建立在 unichars 数组上的。这意味着必须有一些从 NSConstantString 的字符到 NSString 的 unichars 的转换。

由于在 Objective C 中不可能进行运算符重载,这种转换如何/在哪里发生?这里有一些代码生成技巧吗?还是我错过了更明显的东西?

4

2 回答 2

3

这不是框架中唯一一个您会发现您正在处理的类不是您期望的类的地方。由于 Objective-C 是鸭子类型的,因此类之间甚至不需要存在继承关系(尽管这对于让其isKindOfClass:正常工作是可取的)。

使用“前端类”作为接口并使用一堆“私有类”作为实现的做法在 Cocoa 框架中被提升为一种模式。这个概念被称为“类集群”,大多数Foundation类都有自己的集群。由于它们都共享相同的公共接口,因此一切都像您期望的那样工作。就这些而言,前端类本身可能应该被认为是抽象的(即使在 Objective-C 中不存在抽象类的编译时概念)。

例如,一旦你按下运行按钮,两者NSArray都会NSMutableArray变成。NSCFArray另一种公然的鸭子类型:上次我检查时,当你调用一个处理 a 上路径的方法NSString(例如stringByAppendingPathComponent:)时,你会得到一个类的实例NSPathStore2,即使文档说它返回 a NSString

NSConstantString只要NSString所有相关方法都在NSConstantString. 至于转换本身,unichars 的公共访问点并不多:据我统计,只有 5NSString种方法使用unichars,因此任何需要的转换都可以在那里轻松完成。

编辑我更深入一点,发现NSString没有 ivar,就存储而言,它的子类有绝对的自由裁量权。NSSimpleCString声明char* bytesint numBytesNSConstantString不添加 ivar。两个类都实现/覆盖unichar访问方法。

于 2012-08-23T04:16:21.883 回答
1

Objective-C 是一种动态调度语言。您将变量声明为NSString*,但实际上它可以是NSString*. 由于所有方法都是动态分派的(例如方法调用),因此编译器认为对象的类型是什么并不重要[1],重要的是对象实际上是什么。因此,在那行代码中,您的anNSString变量实际上包含 anNSConstantString而不是NSString.

[1]:类型影响选择器查找过程,这会影响编译器认为参数的类型应该是什么,这会影响潜在的警告和类型的隐式强制。这些都与这里无关。

于 2012-08-23T04:16:04.570 回答