我从llvm源代码中注意到编译器支持标志:
-fconstant-string-class=CLASSNAME
如果此标志不存在,编译器似乎默认为NSConstantString。
在检查Apple的Foundation库时,NSConstantString继承自NSSimpleCString,后者提供了启用ObjC Constant String行为所需的ivars。这反过来又是NSString的子类。
但是,在正常的ObjC代码中,以下内容完全合法:
NSString *anNSString = @"This is an NSConstantString?";
这看起来很好(NSConstantString是子类),除了:
1)常量字符串的数据应汇集到NSSimpleCString中声明的ivars中,这对于NSString是不可用的。
2)NSString的迭代方法表明它是基于unichars数组构建的。这意味着必须从NSConstantString的字符转换为NSString的unichars。
由于在目标C中无法进行运算符重载,因此如何/在何处进行此转换?这里有一些代码生成技巧吗?或者我错过了一些更明显的东西?
答案 0 :(得分:3)
这不是框架中唯一一个你会发现你正在处理的课程不是你期望的课程的地方。由于Objective-C是duck-typed,因此甚至不需要在类之间建立继承关系(尽管让isKindOfClass:
正常工作是可取的)。
使用“前端类”作为接口和实现的一堆“私有类”的做法被提升为Cocoa框架中的模式。这个概念称为“类集群”,大多数基础类都有自己的集群。由于它们都共享相同的公共接口,因此一切都像您期望的那样工作。就这些而言,前端类本身应该被认为是抽象的(即使Objective-C中不存在抽象类的编译时概念)。
例如,一旦点击了运行按钮,NSArray
和NSMutableArray
都会成为NSCFArray
。另一个明显的鸭子打字案例:上次我检查过,当你调用一个处理NSString
上的路径的方法时(例如stringByAppendingPathComponent:
),你会得到一个NSPathStore2
类的实例,即使文档说它返回NSString
。
NSConstantString
只要在NSString
中实施/覆盖了所有相关方法,我就不会看到NSConstantString
的ivars对unichar
的影响。至于转换本身,NSString
的公共访问点并不多:根据我的统计,只有5 unichar
种方法使用NSString
s,因此任何所需的转换都可以轻松实现在那里完成。
编辑我走得更远,发现NSSimpleCString
声明没有ivar,就存储而言,绝对酌情决定其子类。 char* bytes
声明int numBytes
和NSConstantString
; unichar
不添加ivar。这两个类都实现/覆盖{{1}}访问方法。
答案 1 :(得分:1)
Objective-C是一种动态调度语言。您将变量声明为NSString*
,但它实际上可能是NSString*
的任何子类。由于所有方法都是动态调度的(例如方法调用),因此编译器认为对象的类型是什么并不重要[1],只关注实际的对象。因此,在该行代码中,anNSString
变量实际上包含NSConstantString
而不是NSString
。
[1]:类型会影响选择器查找过程,这会影响编译器认为参数类型应该是什么,这会影响潜在的警告和类型的隐式强制。这里没有任何相关内容。