In the Cocoa frameworks, it is common to find mutable and immutable versions of classes that store data, such as strings, dictionaries, and arrays. Most of these classes also implement the NSCopying informal protocol, and those with mutable variants implement the NSMutableCopying protocol. These protocols specify methods for obtaining immutable and mutable copies of an object. These copying methods should be implemented such that the copy can return an instance of a subclass, to allow for subclasses to copy their specific instance variables.

There are situations, however, that can result in the inability of a subclass to do so. Consider NSURLRequest:

@interface NSURLRequest : NSObject 

An immutable class, but one that implements NSMutableCopying, it responds directly to the -mutableCopyWithZone:(NSZone *)zone method that returns a mutable url request, an instance of NSMutableURLRequest. While this isn't a problem in itself, it becomes an issue when this method is not re-implemented in NSMutableURLRequest.

– Nope: Implement the NSMutableCopying protocol only in your immutable class.

The implementation of -mutableCopyWithZone:(NSZone *)zone in the immutable class must certainly hard-code the name of the mutable class -- it cannot be aware of any external subclasses of the mutable class. This means that asking for a mutable copy of the immutable class creates an instance of the known mutable subclass. Consider the following example:

@interface MyMutableURLRequest : NSMutableURLRequest {} @end

MyMutableURLRequest *request = [MyMutableURLRequest requestWithURL:url];
request = [request mutableCopy];

In this case, the object returned from -mutableCopy will be an instance of NSMutableURLRequest instead of the expected MyMutableURLRequest.

– Nope: Hardcode class names in -copyWithZone: and -mutableCopyWithZone:

Hardcoding class names serves to block subclassers from subclassing the copy methods without dirty hacks.

+ Yup: [Re]Implement the NSMutableCopying protocol in your mutable class.

By doing this, the class name doesn't have to be hard-coded (in the mutable class), and so a subclasser can simply call [super mutableCopy] and then copy their specific instance variables.

+ Yup: Use [self class] in -copyWithZone: and -mutableCopyWithZone:

By using [self class], an object of the subclass type will be allocated.