Re: Is Apple's singleton sample code correct?
Re: Is Apple's singleton sample code correct?
- Subject: Re: Is Apple's singleton sample code correct?
- From: David Gimeno Gost <email@hidden>
- Date: Sat, 26 Nov 2005 01:17:08 +0100
On 25 Nov 2005, at 18:57, Nick Zitzmann wrote:
1. I believe there is a bug in the following class method:
+ (id)allocWithZone:(NSZone *)zone
{
@synchronized(self) {
if (sharedGizmoManager == nil) {
return [super allocWithZone:zone]; // -> Is this correct?
}
}
return sharedGizmoManager;
}
No, that's correct. It prevents +allocWithZone: from creating a new
instance of the object if the singleton has already been created
(sharedGizmoManager is not nil).
But that's not what the documentations says. It says "Override the
allocWithZone: method to ensure that only the singleton is returned if
someone tries to allocate and initialize an instance of your class
directly instead of using the class factory method".
Thus, according to the documentation, the purpose of overriding
+allocWithZone: as shown in the sample code is to prevent users of the
class from creating more than one instance, no matter what the
circumstances, no matter when, no matter how.
Moreover, at the bottom of the page it specifically says that to allow
for the possibility to create additional instances one should do things
differently: "Situations could arise where you want a singleton
instance (created and controlled by the class factory method) but also
have the ability to create other instances as needed through allocation
and initialization. In these cases, you would not override
allocWithZone: and the other methods following it as shown in Listing
1".
http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaObjects/
Articles/CreateSingleton.html
Given all those explanations, what makes you believe that's intended
behavior? Did you write the code and someone else interpreted it
incorrectly when writing the documentation?
Even if that was intended behavior, I would still consider it bad
design. It unnecessarily creates a strong coupling between different
users of such a class. The behavior of code that calls [[alloc] init]
would depend on whether some unrelated code already had called the
class creation method. There would be no way to know in advance whether
a new instance will be created or the shared one will be returned
instead. And why there should be a way to create new instances before
the shared one has been created but not after? This just doesn't make
sense to me. If the designer of the class wants to allow for multiple
instances to be created in addition to the shared one, then the class
interface should clearly say so by adding a +newInstance method in
addition to the +sharedInstance one.
4. What's the point in overriding the -retain, -release, and
-autorelease methods?
So the singleton can never be deallocated.
And where does that requirement come from? Can you point me to any
document describing the singleton design pattern saying that a
singleton should never be deallocated or destroyed? The GoF "Design
Patterns" book certainly doesn't, nor does any other reference
documentation I'm aware of.
Actually, ensuring that a singleton is properly destroyed when
appropriate is a common design problem that has been discussed
extensively in the C++ literature and in newsgroups such as
comp.lang.c++.moderated. I don't know where the idea that singletons in
Objective-C should never be deallocated comes from, but it certainly is
not part of the singleton design pattern and it is plain wrong.
Singletons that manage resources that should be released at some point
(e.g. when the application quits) should definitely be deallocatable.
But let's pretend for a moment that we are not discussing the general
singleton pattern (whose deallocation should definitely be allowed if
appropriate) and that we are discussing a variation of the singleton
that (for some reason I can't imagine now) shouldn't be deallocated
under any circumstances. Guess what, you don't need to override the
-retain, -release and -autorelease methods at all. All you need to
ensure is that users of your pseudo-singleton class follow the Cocoa
memory management rules. If that's the case, your pseudo-singleton will
never ever be deallocated, no matter what, no matter how, no matter
when, regardless of whether you override those methods or not. The only
way to deallocate it is breaking the rules by releasing more than has
been retained. In other words, the only way to deallocate a singleton
that shouldn't be deallocated is writing buggy code.
So let's consider now that the code that uses your pseudo-singleton is
buggy and releases more than it retains. Do you really think it's a
good idea to override the default (inherited) methods just to silently
hide those bugs making it impossible to detect them, not even by
testing? I don't think so, and such practices certainly shouldn't be
sanctioned by Apple's sample code.
As written in the example, these methods will silently allow the
programmer to write buggy code that doesn't follow Cocoa's memory
management rules.
No they won't. Singletons are not supposed to be deallocated under any
circumstances.
Says who? And why?
5. Does allowing calling -copy and -copyWithZone: on singletons make
sense?
No, but that doesn't stop people from trying it anyway.
And that means we should design our classes so that client code can
misuse them silently and, worse yet, make it impossible to detect such
bugs through testing? I don't think so, and I certainly hope most
programmers don't think so either.
Regards.
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden