5 ms·
- (id)foo tells me that the method returns an object rather than simply performs an action. The article doesn't explain why this makes Objective-C harder or les
by vor_ 13y ago
- (id)foo tells me that the method returns an object rather than simply performs an action. The article doesn't explain why this makes Objective-C harder or less fun. It reminds me of the anal-retentive complaints from long-time NeXTStep developers that I used to see on the Objective-C mailing list before I unsubscribed. Those guys don't even want you saying "call a method" instead of "send a message".
- chc 13y ago-foo would just as definitively indicate that it returns an object. The return type defaults to id, not void. Also, the "call a method"/"send a message" distinction is useful. I don't usually criticize people for using the "method call" terminology, but I almost always use the latter since the idea of messages is central to a lot of Objective-C idioms (e.g. the responder chain in Cocoa). It's helpful to think in terms of messages.
- mikeash 13y agoHow is the call/send distinction useful, exactly? You call a method by sending a message. When you send a message, it calls a method. They're two aspects of the same thing, and using one rather than the other never gives you any additional information.
- chc 13y agoForwarding and dynamic resolution make the relationship between a message send and a method call less than completely straightforward in Objective-C. You do ultimately end up calling some method, but it's not necessarily the method you think you're going to call. I mean, remember: Roughly every Cocoa program in existence routinely calls an unknown method of an unknown object by sending a known message to a known object and having the objects work it out amongst themselves (like I mentioned earlier, the responder chain). Beyond that, I find that mentally framing your program as objects sending messages to each other and responding as they see fit just leads more naturally to good OO designs. It implies a lack of coupling that is absent from the semantics of a "method call."
- poizan42 13y agoHow is that any different from calling a method on a known interface supported by an unknown object in a language such as eg. C# or Java?
- chc 13y agoIf you're going through an interface, it sounds like you have to have a specific object in mind and you just don't know its class. In the pattern I'm talking about, you don't necessarily send the message to the object that will actually respond to the message. You send it to another object and the objects in the chain talk to each other until one agrees to handle it or the end of the chain is reached. This pattern can be used with classes that might not even implement the method. You can do something similar with C# or Java using reflection, but it is more natural in Objective-C.
- mikeash 13y ago> the objects in the chain talk to each other until one agrees to handle it This seems to be greatly overstating the complexity of what happens. There are two cases I can think of that this might describe. One is event messages. This is handled by having everything that can handle an event subclass from NSResponder. NSResponder is then full of little stub methods like this: - (void)mouseDown: (NSEvent *)event { [[self nextResponder] mouseDown: event]; } You then subclass NSResponder and override the methods you're interested in. This would look pretty much the same in any OO language with subclassing and inheritance, which is just about all of them. (NSResponder actually gets a bit clever here, and funnels these methods through a function call that handles general look-up-and-send logic, but the basic principle of what's going on is what you see above.) The other case is action methods with a nil target. Here, there's just a method that looks like this: - (void)sendAction: (SEL)action fromSender: (id)sender { for(id target = [self firstResponder]; target != nil; target = [target nextResponder]) { if([target respondsToSelector: action]) { [target performSelector: action withObject: sender]; break; } } } Again, the real implementation is a bit more clever, but that's the essential part. The use of reflection rules out C++, but it would look pretty much the same in Java. The inside of the loop in Java would look something like: try { Method m = target.getClass().getMethod(action, new Class[]{ Object.class }) m.invoke(target, sender); break; } catch(NoSuchMethodException e) {} The fact that action would have to be a String is a bit smelly, but overall it's pretty much the same code as the Objective-C version. The fact that this pattern isn't used in Java comes down to tradition and happenstance, not any sort of worse affinity on the part of the language.
- mpweiher 13y agoSending a message does not necessarily call a method (especially not the one indicated by the name, messages to nil do nothing, ...), and you can call methods without going through the messenger (get the IMP, call it). Yes they are similar, and most often sending a message of a particular name will invoke a method of that name via the messenger. But they are different in ways that matter, so it is better to use the correct terminology. However, it's not really a big deal, you will typically be understood either way. However, I don't quite understand why using the correct terminology is so difficult. "Send a message" vs. "Call a method". Same number of words, same number of syllables. OK, 1 letter more to type...
- vor_ 13y agoThere's nothing difficult about it. It's just a pedantic and pointless distinction most of the time. To be more specific about what I was referring to, some folks on the Objective-C mailing list didn't even want methods in a protocol to be called methods. Instead they are to be called "method signatures". I roll my eyes.
- mpweiher 13y agoWell, maybe that's because they aren't actually methods? A method is an implementation, something that executes. Protocols do not contain implementations, though there have been proposals to actually add methods to protocols. Talking about such a proposal to add methods to protocols becomes difficult when you have called the messages that are already there methods...
- vor_ 13y ago> -foo would just as definitively indicate that it returns an object. The return type defaults to id, not void. How would it definitely indicate that it returns an object? It has the same signature whether it's an accessor or a behavior, so you don't know if the implementation is returning an object.
- mpweiher 13y ago> It has the same signature whether it's an accessor or a behavior, That turns out not to be the case: -(void)behavior; -accessor;
- jayvanguard 13y agoWhat does drive me nuts is the non-sensical spacing. - (id)foo reduces readability, while -(id) foo is much better. I realize the first one is more common in Apple and is probably more standard, but it begs the question why such a horrible convention ever caught on.
- mpweiher 13y agoHowever, -foo is even better. :-)
- myko 13y agoNo, -foo is confusing and reduces readability.
- mpweiher 13y agoHow so?
- myko 13y agoIt is difficult to tell at a glance if -foo is returning something or just modifying state.
- mpweiher 13y agoNo it's not. If it didn't return anything, it would be -(void)foo; This is how C and by extension, Objective-C work: to indicate "nothing" you have to put in something, specifically "void".
- bennyg 13y agoCall me crazy but I actually like the first way better. It's easier for me to read, personally. Different strokes though.
- dep_b 13y agoApple is wildly inconsistent with their example code and even the templates within XCode when you add a ViewController for example. Same line for the first accolade or the start or the next time in the same file. I always find myself correcting their code, that's just bad.