I'm wondering what the correct pattern for implementing Mutable vs Immutable data structures would be. I understand the concept and how it works, but how should I implement if using an underlying Cocoa data structure? I mean, if I use a NSSet, for instance. Lets say I have the following:
// MyDataStructure.h
@interface MyDataStructure : NSObject
@property (nonatomic, strong, readonly) NSSet * mySet;
@end
// MyDataStructure.m
@interface MyDataStructure ()
@property (nonatomic, strong) NSMutableSet * myMutableSet;
@end
@implementation MyDataStructure
- (NSSet *)mySet
{
return [_myMutableSet copy];
}
@end
The only reason I'm using a mutable set as the underlying data structure,is so that the mutable version of this class can tamper with it. MyDataStructure per se does not really need a mutable set. Therefore, assuming that I have implemented some initialisers to make this class useful, here's how MyMutableDataStructure looks like:
// MyDataStructure.h (same .h as before)
@interface MyMutableDataStructure : MyDataStructure
- (void)addObject:(id)object;
@end
// MyDataStructure.m (same .m as before)
@implementation MyMutableDataStructure
- (void)addObject:(id)object
{
[self.myMutableSet addObject:object];
}
@end
By using this pattern the underlying data structure is always mutable, and its immutable version is just an immutable copy (or is it??).
This also begs another question that arises when implementing the NSCopying protocol. Here's a sample implementation:
- (id)copyWithZone:(NSZone *)zone
{
MyDataStructure * copy = [MyDataStructure allocWithZone:zone];
copy->_myMutableSet = [_myMutableSet copyWithZone:zone];
return copy;
}
Doesn't copyWithZone: return an immutable copy if that applies? So I'm basically assigning a NSSet instead to a NSMutableSet property, isn't that right?
Edit: While diving deeper into the issue I found some more issues surrounding this concern.
mySetshould becopyinstead ofstrong.- My
copyWithZone:implementation isn't right either. I didn't mention it in the first post but that implementation relates to the Immutable version of the data structure (MyDataStructure). As I've read, Immutable data structures don't actually create a copy, they just return themselves. That makes sense. - Because of 2., I needed to override
copyWithZone:in the Mutable version (MyMutableDataStructure).
To make things clear:
// MyDataStructure.h
@property (nonatomic, copy, readonly) NSSet * mySet;
And
// MyDataStructure.m
@implementation MyDataStructure
- (id)copyWithZone:(NSZone *)zone
{
// We don't really need a copy, it's Immutable
return self;
}
- (id)mutableCopyWithZone:(NSZone *)zone
{
// I also implement -mutableCopyWithZone:, in which case an actual (mutable) copy is returned
MyDataStructure * copy = [MyMutableDataStructure allocWithZone:zone];
copy-> _myMutableSet = [_myMutableSet mutableCopyWithZone:zone];
return copy;
}
@end
@implementation MyMutableDataStructure
- (id)copyWithZone:(NSZone *)zone
{
return [self mutableCopyWithZone:zone];
}
@end
It seems tricky at first, but I think I'm getting the hang of it. So the remaining questions are:
- Is the pattern correct?
- Does the getter for
mySetreturn a mutable or immutable instance? - (not listed before) Do I really need the
copysignal when using thecopyproperty attribute?
I appreciate your patience to read this far. Best.
Aucun commentaire:
Enregistrer un commentaire