On 12 Mar 2015, at 10:55, Jonathan Schleifer <[email protected]> wrote:
> As John explained, instancetype takes care of it. However, in a 
> pre-instancetype world, it still works because your assumption is wrong:
> 
>> In order to determine whether the initWithContentsOfFile returns an
>> NSDictionary* or an NSArray*
> 
> Both actually have an initWithContentsOfFile that returns id (or now 
> instancetype). This means they both have the same signature and there's no 
> need for the compiler to know whether it's an NSDictionary or an NSArray. You 
> explicitly tell the compiler the type when you assign it to a variable of 
> that type, but before that, it's only an id for the compiler and it doesn't 
> care.

Or to re-phrase slightly: Unlike C++, where methods with the same name and 
signature on different objects are different messages (unless they explicitly 
inherit from the same superclass), ObjC only has one message (the name, 
including colons is all that decides which message is sent). At the message 
resolution level, ObjC doesn’t distinguish between messages with the same name 
on different objects, nor (and this is where it gets dangerous) between 
messages with the same name but different parameter types.

This means that you need to be careful that the *variable* you store the object 
in that you send a message to has the correct type (instancetype avoids a 
common pitfall, but that’s not the only one). Otherwise the compiler might pick 
the wrong message. A good example (though in the end a rather harmless case) is

        [NSApp setDelegate: myAppDelegate];

This will usually result in an error that myAppDelegate as 
NSObject<NSApplicationDelegate> does not conform to the NSFileManagerDelegate 
protocol. Why? Because NSApp is typed as ‘id’, so it grabs the last definition 
of -setDelegate: it can find, which happens to be NSFileManager’s. In this 
case, this is a harmless warning, as both the sender and the receiver expect 
setDelegate: (id<NSApplicationDelegate>), and ‘id’ is the same size no matter 
what protocol it conforms to. However, the right fix is to write

        [(NSApplication*)NSApp setDelegate: myAppDelegate];

to fix this. Or in this particular case, you should really be using 
[NSApplication sharedApplication] instead of NSApp, which solves the problem 
more elegantly because it actually returns an NSApplication*.

*If* the parameter types of the two parameters differ in important ways, 
though, you might get a crash. E.g. if someone defined a -(void) setDelegate: 
(BOOL)shouldDelegate; method, you’ll likely run into a crash.

So you really want to avoid sending messages to a plain ‘id’ (esp. when it 
comes out of an array) and always assign to a variable of the right type (e.g. 
an id conforming to that protocol, if must be) or typecast it to the right type.

Cheers,
-- Uli Kusterer
“The Witnesses of TeachText are everywhere...”
http://zathras.de


 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Objc-language mailing list      ([email protected])
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/objc-language/archive%40mail-archive.com

This email sent to [email protected]

Reply via email to