Re: Mutable class problems
Re: Mutable class problems
- Subject: Re: Mutable class problems
- From: Ondra Cada <email@hidden>
- Date: Tue, 25 Jun 2002 17:00:56 +0200
On Tuesday, June 25, 2002, at 03:54 , Andy Lee wrote:
I have a slight quibble with this class design, which is having
NSMutableThing subclass from NSImmutableThing. A subclass should extend
its superclass, not adopt a behavior which is expressly banned in the
semantics of the superclass.
It does that, exactly. I fear you don't understand the (im)mutability
design completely.
The practical implication of this is that you can never rely on
compile-time type-checking to be sure that a thing won't be changed out
from under you.
'Course you can't. That would not be possible anyway, since we have a
late-binding, runtime system: allowing compiler to do such check would be
extremely error-prone and just inviting very difficult-to-find bugs when
compiler thinks so, but the runtime reality differs.
You can never write a method of the form...
- (void)foo:(NSImmutableThing *)aThing
{
// Do stuff that absolutely needs aThing to *not* mutate.
}
...without adding a check like this:
- (void)foo:(NSImmutableThing *)aThing
{
if (![aThing isMutable])
{
// Do stuff that absolutely needs aThing to *not* mutate.
}
else
{
// Raise an exception? Return an error code? Ignore?
}
}
Nope, very nope. Both of the above patterns are generally wrong (the
latter slightly less, I'll discuss in more details later). The proper
patterns are
-(void)foo:(NSArray*)a {
// do stuff that does not care whether a is mutable or not
}
-(void)fooImm:(NSArray*)a {
a=[a copy];
// do stuff that absolutely needs a to *not* mutate
}
-(void)fooMut:(NSArray*)a {
a=[a mutableCopy];
// do stuff that absolutely needs a to mutate (please read on if you
wanted a to be shared)
}
Now, there is one more pattern which -- so far as I understand the
Foundation design -- *is proper too*, but does not work due to grave bugs
in the current CoreFoundation-based implementation:
-(void)fooShared:(NSArray*)a { // first variant, rather clean
// for some reason, want always the shared instance, *not* my own copy
[a doMyFoo];
}
// which is accompanied by two categories
@implementation NSArray (MyFoo)
-(void)doMyFoo { ...XXX... }
@end
@implementation NSMutableArray (MyFoo)
-(void)doMyFoo { ...YYY... }
@end
Now, if we for a moment dispense with the nice OO-design, this can be
re-written to something which quite resembles your latter pattern -- just
that the isMutable test of yours is replaced by the appropriate test in
the Foundation way of things (I'd like to point out that it is definitely
not the only possible way, and perhaps not even the best one, but it is
the one Foundation actually uses):
-(void)fooShared:(NSArray*)a { // second variant, unclean, but better
shows the actual point IMHO
// for some reason, want always the shared instance, *not* my own copy
if ([a isKindOfClass:[NSArray class]]) ...XXX...
else /*if ([a isKindOfClass:[NSMutableArray class]])*/ ...YYY...
}
The problem with the Apple CoreFoundation thing is that this "fooShared"
pattern (in both variants) does not work, and -- so far as I understand
Chris' mails -- there is absolutely no workaround which would not be
implementation-dependent (ie., non-portable, possibly even between
different OSX releases).
---
Ondra Cada
OCSoftware: email@hidden
http://www.ocs.cz
private email@hidden
http://www.ocs.cz/oc
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.