NSCopying and Mutability
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.
1 comments:
contra at 2009-05-17 18:00:45 -0400
Very informative post. Thanks for sharing these links with us. I am a new blogger that’s why I am searching some tips and post that can give me some knowledge.