I have noticed from the llvm source code that the compiler supports the flag:
-fconstant-string-class=CLASSNAME
If this flag is not present, the compiler appears to default to NSConstantString.
Upon inspection of Apple’s Foundation Library, NSConstantString inherits from NSSimpleCString which provides the required ivars to enable ObjC Constant String behaviour. This in turn is a child class of NSString.
However, in normal ObjC code, the following is perfectly legal:
NSString *anNSString = @"This is an NSConstantString?";
This seems fine (NSConstantString is the child class), except:
1) The data of a constant string should be funnelled into the ivars declared in NSSimpleCString, which are not available to an NSString.
2) NSString’s iteration methods suggest it is built on arrays of unichars. This means there must be some conversion from NSConstantString’s chars to NSString’s unichars.
As operator overloading is not possible in Objective C, how/where could this conversion take place? Is there some code generation trickery going on here? Or have I missed something more obvious?
This is not the only place in the framework you’ll find that the class you’re dealing with is not the class you’re expecting. As Objective-C is duck-typed, there doesn’t even need to be an inheritance relationship between the classes (although this would be desirable to let
isKindOfClass:work correctly).The practice of using a “front class” as an interface and a bunch of “private classes” for the implementation is elevated to a pattern in the Cocoa framework. This concept is called a “class cluster”, and most Foundation classes have their own cluster. Since they all share the same public interface, everything works just like you would expect. As far as those are concerned, the front classes themselves should probably be considered abstract (even though the compile-time concept of an abstract class doesn’t exist in Objective-C).
For instance, both
NSArrayandNSMutableArraybecomeNSCFArrayonce you hit the run button. Another case of blatant duck typing: last time I checked, when you call a method that deals with paths on aNSString(for examplestringByAppendingPathComponent:), you get an instance of theNSPathStore2class, even though the documentation says it returns aNSString.I don’t see how
NSConstantString‘s ivars could be of matter toNSStringso long as all relevant methods are implemented/overridden inNSConstantString. As for the conversion itself, there aren’t that many public access points tounichars: by my count, only 5NSStringmethods useunichars, so any required conversion could easily be done there.EDIT I went a little deeper and found out
NSStringdeclares no ivar, leaving absolute discretion to its subclasses as far as storage is concerned.NSSimpleCStringdeclareschar* bytesandint numBytes;NSConstantStringadds no ivar. Both classes implement/overrideunicharaccess methods.