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]