knowledge-database (beta)

Current group: comp.lang.objective-c

return of init

return of init  
Laurent Deniau
 Re: return of init  
Michael Ash
 Re: return of init  
Joe Shimkus
 Re: return of init  
Michael Ash
 Re: return of init  
Joe Shimkus
 Re: return of init  
Philippe Mougin
 Re: return of init  
Laurent Deniau
 Re: return of init  
Christian Brunschen
 Re: return of init  
Laurent Deniau
 Re: return of init  
Gregory Weston
 Re: return of init  
Michael Ash
From:Laurent Deniau
Subject:return of init
Date:Fri, 03 Dec 2004 09:52:44 +0100
Does anybody have *good examples* where init should return something
else than the incoming object? I have searched for meaningful examples
and explanation on the web, including the apple web site without success.

The only useful case I can imagine is to add one more indirection to
self (e.g. for registration somewhere) but then received messages by the
indirect self should be delegated to next level, that is the true self.
I do not see example where self could be safely replaced by another object.

Thanks.

a+, ld.
From:Michael Ash
Subject:Re: return of init
Date:Fri, 03 Dec 2004 05:54:07 -0600
Laurent Deniau wrote:
> Does anybody have *good examples* where init should return something
> else than the incoming object? I have searched for meaningful examples
> and explanation on the web, including the apple web site without success.
>
> The only useful case I can imagine is to add one more indirection to
> self (e.g. for registration somewhere) but then received messages by the
> indirect self should be delegated to next level, that is the true self.
> I do not see example where self could be safely replaced by another object.

Look up Class Clusters in the Apple docs for one widespread use.
Basically, classes like NSString actually have a bunch of hidden, private
subclasses which are all specialized for different uses. When you do
[[NSString alloc] init], you don't get an NSString back, you get an
instance of one of these private subclasses.

Another use is for writing singleton classes. Normally when you write a
singleton, you just provide a +sharedInstance method and document
somewhere that you shouldn't alloc/init the class. However, you can
override init like so:

- init {
if(sharedInstance) {
[self release];
return [sharedInstance retain];
}
....do setup here....
}

One advantage of this approach is that you can do things like instantiate
the singleton in a nib and still have the same object everywhere.
From:Joe Shimkus
Subject:Re: return of init
Date:Sat, 04 Dec 2004 01:25:32 -0500
In article <1102074847.661944@nfs-db1.segnet.com>,
Michael Ash wrote:

> Another use is for writing singleton classes. Normally when you write a
> singleton, you just provide a +sharedInstance method and document
> somewhere that you shouldn't alloc/init the class. However, you can
> override init like so:
>
> - init {
> if(sharedInstance) {
> [self release];
> return [sharedInstance retain];
> }
> ....do setup here....
> }
>

Funny, I just did the above recently so that anybody who uses the class
doesn't shoot themselves in the foot by alloc/init.

> One advantage of this approach is that you can do things like instantiate
> the singleton in a nib and still have the same object everywhere.

How do you do this? I'm using a static file scope variable as a sort-of
class variable to hold the shared instance reference. Can you actually
do a connection to it (static or not) through IB where you have an
extern declaration in the class header file something like:

IBOutlet extern ClassFoo *sharedInstance;

with the corresponding definition in the .m file?

--
PGP Key (DH/DSS): http://www.shimkus.com/public_key.asc
PGP Fingerprint: 89B4 52DA CF10 EE03 02AD 9134 21C6 2A68 CE52 EE1A

Windows has always aspired to be Mac-like without Microsoft ever really
understanding what that even means. - Robert Cringely
From:Michael Ash
Subject:Re: return of init
Date:Sat, 04 Dec 2004 03:06:57 -0600
Joe Shimkus wrote:
> In article <1102074847.661944@nfs-db1.segnet.com>,
> Michael Ash wrote:
>
>> Another use is for writing singleton classes. Normally when you write a
>> singleton, you just provide a +sharedInstance method and document
>> somewhere that you shouldn't alloc/init the class. However, you can
>> override init like so:
>>
>> - init {
>> if(sharedInstance) {
>> [self release];
>> return [sharedInstance retain];
>> }
>> ....do setup here....
>> }
>>
>
> Funny, I just did the above recently so that anybody who uses the class
> doesn't shoot themselves in the foot by alloc/init.
>
>> One advantage of this approach is that you can do things like instantiate
>> the singleton in a nib and still have the same object everywhere.
>
> How do you do this? I'm using a static file scope variable as a sort-of
> class variable to hold the shared instance reference. Can you actually
> do a connection to it (static or not) through IB where you have an
> extern declaration in the class header file something like:
>
> IBOutlet extern ClassFoo *sharedInstance;
>
> with the corresponding definition in the .m file?

No, that doesn't work. All you do is just implement -init as above, then
select the class and do "Instantiate MyClass" as normal. As far as IB is
concerned, it's going to get a new instance of your class. However, the
nib loader is just going to do [[class alloc] init] when it creates this
instance. If your implementation of -init actually returns your singleton,
then of course you'll get the singleton into the nib.
From:Joe Shimkus
Subject:Re: return of init
Date:Sat, 04 Dec 2004 14:33:41 -0500
In article <1102151217.198098@nfs-db1.segnet.com>,
Michael Ash wrote:

> No, that doesn't work. All you do is just implement -init as above, then
> select the class and do "Instantiate MyClass" as normal. As far as IB is
> concerned, it's going to get a new instance of your class. However, the
> nib loader is just going to do [[class alloc] init]

Doh! Of course.

--
PGP Key (DH/DSS): http://www.shimkus.com/public_key.asc
PGP Fingerprint: 89B4 52DA CF10 EE03 02AD 9134 21C6 2A68 CE52 EE1A

Windows has always aspired to be Mac-like without Microsoft ever really
understanding what that even means. - Robert Cringely
From:Philippe Mougin
Subject:Re: return of init
Date:3 Dec 2004 20:11:47 -0800
Laurent Deniau wrote in message news:...
> Does anybody have *good examples* where init should return something
> else than the incoming object? I have searched for meaningful examples
> and explanation on the web, including the apple web site without success.

There is an interesting example in the article "Obj-C Optimization:
Allocation Basics & Foundation" at
http://www.mulle-kybernetik.com/artikel/Optimization/opti-2.html (the
example is at the end of the article, in the section titled "Does
Foundation suck?").

BTW, this article is part of a famous articles series available at
http://www.mulle-kybernetik.com/artikel/Optimization/

Best,

Philippe Mougin
http://www.fscript.org - Interactive and scripting environment for
Cocoa
From:Laurent Deniau
Subject:Re: return of init
Date:Tue, 07 Dec 2004 11:39:11 +0100
Philippe Mougin wrote:
> Laurent Deniau wrote in message news:...
>
>>Does anybody have *good examples* where init should return something
>>else than the incoming object? I have searched for meaningful examples
>>and explanation on the web, including the apple web site without success.
>
>
> There is an interesting example in the article "Obj-C Optimization:
> Allocation Basics & Foundation" at
> http://www.mulle-kybernetik.com/artikel/Optimization/opti-2.html (the
> example is at the end of the article, in the section titled "Does
> Foundation suck?").

Thanks for the links.

I have read the article and I am still not convince by the need for an
init returning self. If I understand well, all this machinery
(NSPlaceHolderString) is just because they want to put the string
characters in the same storage as the String itself, and avoid another
malloc. Right?

BTW, the article starts with data alignment and saving space. But I saw
nothing about the reference counter. I thought that reference counter is
stored in the object just after isa. Right? Is is an unsigned short or
an unsigned int?

Finally, I saw many times in Objective-C code

id obj = [[class alloc] init];

What happens to the allocated object in alloc if init raises an exception?

Thanks.

a+, ld.
From:Christian Brunschen
Subject:Re: return of init
Date:7 Dec 2004 12:05:20 GMT
In article ,
Laurent Deniau wrote:

>I have read the article and I am still not convince by the need for an
>init returning self. If I understand well, all this machinery
>(NSPlaceHolderString) is just because they want to put the string
>characters in the same storage as the String itself, and avoid another
>malloc. Right?

No. There are different NSString subclasses to handle different types of
string. For instance, to create a string object that references a
sub-range of another string object, one could devise an NSSubString class
which could referenc the original string, rather than making its own copy
(if the original String is an immutable one). Similarly, if you have
different character encodings and character sets, you may be able to have
specific subclasses which are optimized to handle that particular encoding
or character set.

All of these subclasses would still be instantiated through one of
NSString's '-init...' methods. The NSPlaceholderString object that is
returned from NSString's +alloc simply dispatches the -init... method as
necessary, to instantiate an object of the appropriate subclass.

>BTW, the article starts with data alignment and saving space. But I saw
>nothing about the reference counter. I thought that reference counter is
>stored in the object just after isa. Right? Is is an unsigned short or
>an unsigned int?

No. Cocoa actually uses out-of-line reference counts for most of its
classes, IIRC, and only actually stores retain counts for objects whose
retain count becomes > 1 . Since many objects have such a simple
lifecycle, it cold be considered a waste to store the reference count if
it never does anything than start at 1 and then go down to 0, so using an
out-of-line reference count, that storage space can be saved - which may
make a significant sifference, especially for small objects.

>Finally, I saw many times in Objective-C code
>
>id obj = [[class alloc] init];
>
>What happens to the allocated object in alloc if init raises an exception?

The same thing that usually happens if an exception gets raised. There is
absolutely nothing magical about +alloc or -init. If you have an exception
handler somewhere that will intercept the raised exception, that will get
called; otherwise, I expect the unhandled exception may cause your
application to terminate.

Generally, though, a failure to allocate and/or initialize an instance
will be signalled by way of the returned object being 'nil', so you should
check for that.

>Thanks.

Best wishes,

>a+, ld.

// Christian Brunschen
From:Laurent Deniau
Subject:Re: return of init
Date:Tue, 07 Dec 2004 14:24:06 +0100
Christian Brunschen wrote:
> In article ,
> Laurent Deniau wrote:
>
>
>>I have read the article and I am still not convince by the need for an
>>init returning self. If I understand well, all this machinery
>>(NSPlaceHolderString) is just because they want to put the string
>>characters in the same storage as the String itself, and avoid another
>>malloc. Right?
>
>
> No. There are different NSString subclasses to handle different types of
> string. For instance, to create a string object that references a
> sub-range of another string object, one could devise an NSSubString class
> which could referenc the original string, rather than making its own copy
> (if the original String is an immutable one). Similarly, if you have
> different character encodings and character sets, you may be able to have
> specific subclasses which are optimized to handle that particular encoding
> or character set.
>
> All of these subclasses would still be instantiated through one of
> NSString's '-init...' methods. The NSPlaceholderString object that is
> returned from NSString's +alloc simply dispatches the -init... method as
> necessary, to instantiate an object of the appropriate subclass.

I was talking only of -init not -init... I do not see in -init how you
can switch to another class better than directly in +alloc without
add-in information. About the -init... if the underlying object is not
the one asked for then you are returning an object of mutable type (in
the Liskov sens). So what you do can only be done with langages which
support either genericity or dynamic message dispatch (like ObjC). The
later forbid optimization through static message resolution since you
use the primary class only as a class dispatcher and object factory. In
that case, why not directly provide a +newConstantString and disable
-init to underline the point since the +alloc -init scheme is not
anymore suitable for these constructions and may even be dangerous if
used by further derivation?

>>BTW, the article starts with data alignment and saving space. But I saw
>>nothing about the reference counter. I thought that reference counter is
>>stored in the object just after isa. Right? Is is an unsigned short or
>>an unsigned int?
>
>
> No. Cocoa actually uses out-of-line reference counts for most of its
> classes, IIRC, and only actually stores retain counts for objects whose
> retain count becomes > 1 . Since many objects have such a simple
> lifecycle, it cold be considered a waste to store the reference count if
> it never does anything than start at 1 and then go down to 0, so using an
> out-of-line reference count, that storage space can be saved - which may
> make a significant sifference, especially for small objects.

Right. But how do you retrieve the reference counter when you need to
know its value (I am not talking about the message, but about the
underlying structure, array, hash table, ...). Because if the counter is
stored in a third-party object then the efficiency of retrieving its
value (base on the object address?) could be rather slow. This could
introduce a huge penalty for cases where you need to know for example if
refcnt > 1 and ask for a clone before doing a write access to the shared
object.

>>Finally, I saw many times in Objective-C code
>>
>>id obj = [[class alloc] init];
>>
>>What happens to the allocated object in alloc if init raises an exception?
>
>
> The same thing that usually happens if an exception gets raised. There is
> absolutely nothing magical about +alloc or -init. If you have an exception
> handler somewhere that will intercept the raised exception, that will get
> called; otherwise, I expect the unhandled exception may cause your
> application to terminate.

I was talking about the ressources leaks. I have the feeling that most
ObjC code is not exception safe. I agree that it quite difficult to make
such code, but as soon as you have exception in ObjC, you should write
exception-safe code. Don't you?

> Generally, though, a failure to allocate and/or initialize an instance
> will be signalled by way of the returned object being 'nil', so you should
> check for that.

AFAIR, sending a message to nil does nothing and return nil. So does it
means that after all [[class alloc] init], one should still check for a
nil id? (something that I never see in the example/paper).

Thanks.

a+, ld.
From:Gregory Weston
Subject:Re: return of init
Date:Tue, 07 Dec 2004 16:45:02 GMT
In article ,
Laurent Deniau wrote:

> >>BTW, the article starts with data alignment and saving space. But I saw
> >>nothing about the reference counter. I thought that reference counter is
> >>stored in the object just after isa. Right? Is is an unsigned short or
> >>an unsigned int?

It's an unsigned int, according to the docs.

> > No. Cocoa actually uses out-of-line reference counts for most of its
> > classes, IIRC, and only actually stores retain counts for objects whose
> > retain count becomes > 1. ...
>
> Right. But how do you retrieve the reference counter when you need to
> know its value (I am not talking about the message, but about the
> underlying structure, array, hash table, ...). Because if the counter is
> stored in a third-party object then the efficiency of retrieving its
> value (base on the object address?) could be rather slow. This could
> introduce a huge penalty for cases where you need to know for example if
> refcnt > 1 and ask for a clone before doing a write access to the shared
> object.

a) It doesn't introduce a huge penalty. The mechanism used is sufficient
for heavy use.
b) I might question your reliance on the retain count to control
anything other than memory management. It's a black box.

G

--
Change account to gw when responding by mail.
From:Michael Ash
Subject:Re: return of init
Date:Tue, 07 Dec 2004 11:01:17 -0600
In article you wrote:
>>
>> All of these subclasses would still be instantiated through one of
>> NSString's '-init...' methods. The NSPlaceholderString object that is
>> returned from NSString's +alloc simply dispatches the -init... method as
>> necessary, to instantiate an object of the appropriate subclass.
>
> I was talking only of -init not -init... I do not see in -init how you
> can switch to another class better than directly in +alloc without
> add-in information.

You can't. However, the other -initWith... methods exist, and so using an
alloc/init combo keeps things consistent.

> About the -init... if the underlying object is not
> the one asked for then you are returning an object of mutable type (in
> the Liskov sens). So what you do can only be done with langages which
> support either genericity or dynamic message dispatch (like ObjC). The
> later forbid optimization through static message resolution since you
> use the primary class only as a class dispatcher and object factory. In
> that case, why not directly provide a +newConstantString and disable
> -init to underline the point since the +alloc -init scheme is not
> anymore suitable for these constructions and may even be dangerous if
> used by further derivation?

The entire point of the alloc/init combo is to separate object creation
from object initialization. I can write a new alloc method (say,
allocFromCache or something) without having to do a lot of evil behind the
scenes. It also makes a lot of sense to have init be an instance method
rather than a class method, where you have to do evil things like
reassigning 'self', directly twiddling instance variables, or you're
restricted to doing all of your initialization via accessors. Without the
alloc/init separation, your creation code is uglier, and you get a
combinatorial explosion if you want to have more than one way to create an
object.

>> No. Cocoa actually uses out-of-line reference counts for most of its
>> classes, IIRC, and only actually stores retain counts for objects whose
>> retain count becomes > 1 . Since many objects have such a simple
>> lifecycle, it cold be considered a waste to store the reference count if
>> it never does anything than start at 1 and then go down to 0, so using an
>> out-of-line reference count, that storage space can be saved - which may
>> make a significant sifference, especially for small objects.
>
> Right. But how do you retrieve the reference counter when you need to
> know its value (I am not talking about the message, but about the
> underlying structure, array, hash table, ...). Because if the counter is
> stored in a third-party object then the efficiency of retrieving its
> value (base on the object address?) could be rather slow. This could
> introduce a huge penalty for cases where you need to know for example if
> refcnt > 1 and ask for a clone before doing a write access to the shared
> object.

Given how common retain and release are, one would assume that retrieving
an object's refcount is fairly fast. It's not as fast as as storing it
inline, of course. This design decision was made back when a savings of
four bytes per object was a big deal. I have a feeling it also makes
thread safety quite a bit easier, though.

However, you should not be writing code that inspect's an object's
reference count for purposes other than debugging. There are exceptions,
but they are rare. Circumstances like the one you describe are generally
handled with the mutable/immutable distinction and defensive copies. If
you want an object that's guaranteed not to change, copy it. If it's
immutable, then copy will end up just retaining it for you. This has the
same kinds of advantages, but it won't break just because somebody did a
[[obj retain] autorelease] and the autorelease pool didn't pop yet.

>>>Finally, I saw many times in Objective-C code
>>>
>>>id obj = [[class alloc] init];
>>>
>>>What happens to the allocated object in alloc if init raises an exception?
>>
>> The same thing that usually happens if an exception gets raised. There is
>> absolutely nothing magical about +alloc or -init. If you have an exception
>> handler somewhere that will intercept the raised exception, that will get
>> called; otherwise, I expect the unhandled exception may cause your
>> application to terminate.
>
> I was talking about the ressources leaks. I have the feeling that most
> ObjC code is not exception safe. I agree that it quite difficult to make
> such code, but as soon as you have exception in ObjC, you should write
> exception-safe code. Don't you?

If you throw an exception from init, then you should release self first.
Otherwise, it's just like anything else.

Writing exception-safe ObjC code doesn't seem too horrible. The
autorelease pool makes it easier, since autoreleased objects will
eventually be released even if an exception is thrown. That means that
typical Cocoa code, which rarely calls alloc but rather calls lots of
convenience constructors (like the +stringWith... methods) will generally
not leak by default. Any time you're manually writing an
alloc/init/release sequence, you have to be careful to release the object
if an exception occurs in the middle, but this is fairly rare.

>> Generally, though, a failure to allocate and/or initialize an instance
>> will be signalled by way of the returned object being 'nil', so you should
>> check for that.
>
> AFAIR, sending a message to nil does nothing and return nil. So does it
> means that after all [[class alloc] init], one should still check for a
> nil id? (something that I never see in the example/paper).

There is only one way that alloc will fail on a modern system, and that is
if you run out of address space. If you actually run out of memory (not
the same as running out of address space), then there is no way to detect
or recover from the problem on a modern OS, due to lazy allocation
strategies. It is more possible that -init will fail, depending on which
-init message you're sending, but this is documented.

Very often, you don't need to check, and you can just cascade the nil
through all of your messages without ever needing to check. Example:

- (NSData *)checksumOfFile:(NSString *)file {
NSMutableData *fileData = [[NSMutableData alloc]
initWithContentsOfFile:file]; // returns nil if file doesn't exist, etc.
[fileData appendData:salt]; // is a NOP if fileData is nil
NSData *md5 = [fileData md5Hash]; // returns nil if fileData is nil
[fileData release]; // is a NOP if fileData is nil
return md5;
}

Here's a method which returns nil on error, with no explicit checks. This
isn't always the case with every piece of code, but it often works out
nicely.
   

Copyright © 2006 knowledge-database   -   All rights reserved