Why does [NSMutableString stringWithString: @ ""] work?

Just wondering:

There is a static method in NSString called +stringWithString: This is not overridden / overridden in NSMutableString , so we cannot assume that this will return NSMutableString . In fact, even in the NSString class, the return type is defined as id , and doc states :

Return value
String created by copying characters from aString .

What part of the purpose of C do I lack in my knowledge to understand why this works and returns an NSMutableString ? Moreover, the base class NSString does not know that we want to return a mutable string.

We can say that internally [Class alloc] is called, which will generate an object of type NSMutableString , but even this is pure guesswork, since we do not have the source code, and stringWithString: can do whatever it wants inside.

Are all these class methods overridden in a subclass? And if so, why is this not documented?

+7
source share
4 answers

There is a static method in NSString called + stringWithString :.

in a more appropriate way, this is a class method.

It is not overridden / overridden in NSMutableString

In cocoa, the subclass does not need to reuse the method. In fact, it would just make a lot of noise (IMO). This is only necessary to override the method to ensure its custom implementation.

therefore, we cannot assume that this will return an NSMutableString.

We must assume that it will return a volatile string. A subclass can redefine its initializers and convenience constructors as necessary to satisfy the required contracts without publicly reusing the method - it only needs to define a method when the underlying implementation is insufficient.

What part of the purpose of C do I lack in my knowledge to understand why this works and returns an NSMutableString? Moreover, the base class NSString does not know that we want to return a variable string.

He "knows" because you wrote [NSMutableString stringWithString:@"bah"] , and not [NSString stringWithString:@"bah"] . Like instance methods, class methods have an implicit self that allows them to pass a type through class methods. Therefore, class methods can be overridden / redefined as needed. Class methods can also use self to define or report their type (an example is coming soon).

We can say that internally [Class alloc] is called, which will generate an object of type NSMutableString, but even this is pure guesswork, since we do not have source code and stringWithString: it can do whatever it wants inside.

This should not be a hunch. In this case, you should indicate an error if an immutable string was returned to you. Otherwise, it works as advertised, regardless of whether they used one or more definitions.

Are all these class methods overridden in a subclass?

In the case of convenience constructors, one of the designated initializers is more common:

such an implementation may take the form:

 @implementation NSString + (id)stringWithString:(NSString *)arg { // self is either +NSString or +NSMutableString return [[[self alloc] initWithString:arg] autorelease]; } 

although exceptions can often be made, and often this happens with optimized immutable / mutable types:

 @implementation NSString + (id)stringWithString:(NSString *)arg { return [arg imp_isMutable] ? [[[self alloc] initWithString:arg] autorelease] : arg; } ... @implementation NSMutableString + (id)stringWithString:(NSString *)arg { return [[[self alloc] initWithString:arg] autorelease]; } ... 

And if so, why is this not documented?

They should not be re-documented or re-documented when the only difference is the type of class that you requested, unless they deviate from the base class or special note - even then it would be better to create a method with a different name.

+6
source

NSMutableString is a subclass of NSString , so any method called NSMutableString can work properly and return NSMutableString when it makes sense. The only method that comes to mind that does not follow this, although there is copy , which, by convention, returns an immutable instance.

This is why your initialization methods return an id rather than a specific instance, and why all class methods should use [self alloc] instead of [MYActualClass alloc] .

+3
source

You can write the initializer a little as follows:

 + (id) stringWithString: (NSString*) foo { return [[self alloc] initWithString:foo]; } 

Now, when you call this initializer on NSString , [self alloc] returns NSString , and you get an instance of NSString back. But when you call [NSMutableString stringWithString:@"…"] , the result of the [self alloc] message is NSMutableString , and therefore the initializer returns a mutable string.

+3
source

(What Justin said, but clarification)

There is a static method in NSString called + stringWithString :. This one is not overridden / overridden in NSMutableString, so we cannot assume that this will return NSMutableString. In fact, even in an NSString class, the return type is defined as id ...

First of all, Objective-C has no static methods. Objective-C has class methods . Class methods behave exactly like instance methods (where the class is an instance of a metaclass) and can be inherited, redefined, etc.

This way, just like NSMutableString inherits characterAtIndex: and can override it to do something special, if necessary, NSMutableString can do the same for class methods.

Also note that a class should not declare a method in the header that it overrides from its superclass. Classes in the structure usually do not declare overridden methods explicitly because the overridden method must behave exactly like the parent, but is redefined to work in the context of the requirements of the subclass.

+3
source

All Articles