Re: Mutable classes and class clusters
Re: Mutable classes and class clusters
- Subject: Re: Mutable classes and class clusters
- From: Peter Ammon <email@hidden>
- Date: Sat, 15 Sep 2001 18:15:02 -0400
On Saturday, September 15, 2001, at 03:48 PM, Rob Rix wrote:
Hello, all.
After some checking through the archives, I wasn't able to find the
answers I wanted (*grin*), so I'm checking here now.
My questions:
1) What benefits do separate immutable and mutable classes provide? I'm
developing a framework, and I'm wondering whether I should separate the
mutable aspects of some of my classes into a mutable subclass.
It occurs to me that the rationale behind this decision might have been
the fact that NSArray et al are class clusters. Is this the case?
John Hvrnkvist gave a good point, but another reason is performance.
When you send a copy message to a mutable object, it has to actually
allocate another object, but an immutable object can simply retain
itself and return self (and you can test yourself that the pointer you
get back from a copy message sent to an immutable string is the same),
which is faster and uses less memory. An NSMutableArray is likely to
keep some extra space around at the end of the array for adding more
object on to it, but an immutable NSArray can use just enough space to
hold all of its objects, saving on memory. Likewise, the docs say that
NSCharacterSet is much faster than NSMutableCharacterSet (anyone know
why?)
If you know that your object won't change, you can take advantage of a
lot of powerful techniques for making it faster. For example, you can
often forgo locks on accesses to immutable objects from different
threads. Or you might want to invest in a perfect hash for
constant-time searching of the object.
So you might want to go to mutable and immutable types if you expect
your classes will be used in performance-sensitive contexts and you can
realize a speed increase from doing so.
2) One of the classes I'm implementing in my framework is about to be
redesigned as a class cluster, with a single public class (unless I
find that separating it into mutable and immutable would be worthwhile,
of course). So, to make a class cluster, is all that is involved
changing my class' -(id)init method so that it returns an instance of a
private subclass? Should I also have said private subclasses report
that they are actually members of the superclass when queried with
things like -isMemberOfClass, -class, and +class?
Thanks very much,
There's typically more to it than that. You probably will want to
create a sort of proxy member of your class cluster, with no instance
variables, and override alloc to return an instance of that. Then
implement your various init methods in that proxy class, and in each of
them destroy the instance of the proxy class method (aka self) and
allocate and initialize the right member of your class cluster.
As far as I can tell, this is what Apple does. For example, consider
the following code:
NSString* string=[NSString alloc];
NSLog(@"Pre-init address %p Description: %@", string, [string
class]);
string=[string initWithCString:"Hello World"];
NSLog(@"Post-init address %p Description: %@", string, [string
class]);
On my machine, this prints
Pre-init address 0xe5b30 Description: NSPlaceholderString
Post-init address 0xe5a8d0 Description: NSCFString
Notice two things: the existence of a proxy class "NSPlaceholderString"
and the fact that the initialized string has a different address than
the uninitialized string.
Also notice that the class message reports the actual class of the
object instead of claiming to be members of the superclass, so I
wouldn't override those methods if I were you. Clueful Cocoa
programmers know to use isKindOfClass: rather than isMemberOfClass: when
potentially dealing with class clusters anyways.
Hope this helps.
-Peter