Dynamic binding -- Qt's Signals and Slots vs Objective-C
Lutger
lutger.blijdestijn at gmail.com
Wed Sep 27 08:55:03 PDT 2006
Fredrik Olsson wrote:
<snip>
> How Obj-C Cocoa does it:
>
> Each object can have an action and a target. An action is an event that
> is signaled at run-time, and the target is an object instance to call.
> If target is nil (null) then the action will be sent to the responder
> chain, instead of a predestined object.
>
> The responder chain is implemented in the NSResponder protocol
> (Interface) and will send the action down the controllers is logical
> order acording to how windows are stacked, ending up in the
> NSApplication instance if no one else is interested. This make sure that
> if a single menu item (OSX == one menu you know :) ) has nil as target,
> then the topmost window will get a chance to respond first, and yet the
> same item will work for all windows.
>
> You connect an action/target like this:
> [obj1 setAction:@selector(valueChanged:)];
> [obj1 setTarget:obj2];
>
> And you can later "emit" the action using:
> [obj1 sendAction:[obj1 action] to:[obj1 target]];
> which will cause the valueChanged: method of obj2 to be performed. In
> reality most classes have shortcuts such as sendAction, and even more so
> you rarely need to care about sending manually at all.
Sounds good, but isn't it quite possible to implement this in D with a
more flexible messaging system than templated S&S?
>> - Qt requires derivation from QObject to participate in S&S. Does
>> Obj-C also require deriving from a particular base object? Is it
>> explicit?
> More or less. All existing senders are subclasses of NSControl, so using
> those subclasses will let you use say [foo sendAction], and such shorter
> things. In the same way subclasses of NSResponder will automatically fit
> in the responder chain.
>
> But in practice, Obj-C will not care as much of the classes, but of what
> the classes implement. So if you send the action foo: to bar what the
> run-time will do is a:
> if ([bar respondsToSelector:@selector(foo:)]) {
> [bar performSelector:@selector(foo:)];
> }
This is also a benefit of templates, no need for a superclass and free
functions, literal functions and delegates work too.
> And yes, if it does not respond, it is no error, unless you want it to
> be, it is perfctly legal to call methods that are not implemented :).
>
>> - What is the overhead to support Obj-C messaging in a class? Is
>> there a way to create an Obj-C class that doesn't support messaging?
> The Obj-C language is build upon this message dispatch, so no way around
> it, each "method call" is a message dispatch. And there is a overhead as
> compared to C++. The run-time uses caching and other neat tricks, so in
> practice a Obj-C method call cost about 2.5 C++ method calls.
According to QT, templated S&S is approximately 4x the cost of a
function call and QT's S&S is 10x the cost. So 2.5 certainly looks
acceptably to me, but this cost is paid for all calls right? And if I
understood this correctly, this also means Obj-C cannot inline member
functions?
>> - Do people use Obj-C messaging for anything besides GUIs?
> Oooh, yes. The real power here is in the dynamic dispatching of
> messages. Best of all is what is called categories. You can extend a
> class by subclassing, or by adding a category.
>
> NSArray is a base class for static arrays.
> NSMutableArray is a subclass of NSArray that is mutable (dynamic).
> If you wanted to add a method say something useful as reversedArray to
> them, then in C++ (And D) you would need to make two subclasses, one to
> NSArray, and one to NSMutableArray, and it would be dead on impossible
> make a function accept both without typecasting (Ok, add an interface
> then). In Obj-C you can instead add a category to NSArray, and it will
> automatically be added to all subclasses as well. Like this:
> @interface NSArray (ReversedCat)
> - (NSArray *)reversedArray;
> @end
>
Thanks for this explanation,I'm going to look into this Objective C
thing as it seems interesting.
><snip>
>> I've heard many people in C++ land say things to the effect of "Bah,
>> those silly Qt people weren't smart enough realize that you can
>> implement signals and slots directly in C++". But I've not been
>> particularly impressed by the pure C++ S&S libraries I've seen. On
>> the other hand, I found Qt's S&S to be simple, clean, straightforward,
>> and very easy to use. And I've not heard anything but praise about
>> making GUIs with Obj-C. Lutger's S&S for D posted earlier looks very
>> nice, but there must be something neat that Qt S&S--being dynamic--can
>> do that isn't possible with the static S&S solutions. Like
>> enumerating available signals for use in a GUI builder tool.
Yes, you could say they fulfill different purposes. This article
compares them and even makes a point of using them side by side:
http://www.scottcollins.net/articles/a-deeper-look-at-signals-and-slots.html
>> - Is it possible to mix D-style classes with Obj-C style messaging?
>> Apple's Objective-C++ apparently doesn't allow it.
>> http://developer.apple.com/releasenotes/Cocoa/Objective-C++.html
>> I.e. a class is either a C++ class or an Obj-C class. They can call
>> each other, but they are separate. You can't send an Obj-C message to
>> a C++ class. I think the ideal, though, would be something closer to
>> Qt where you have the ability to make any method you want be a slot.
>> In Qt those methods remain valid C++ methods, but you can also call
>> them by name, effectively.
>>
> This is because C++/D and Obj-C works very differently. Lets call the
> object that will have a method called the reciever.
>
> What C++/D does is very simply put: classes are structs with hidden
> function pointers, when calling a method it looks up the function
> pointer at a static offset from the reciever, and jumps. And the class
> better make sure there is a valid function at the other end.
>
> What Obj-C does is that it takes the reciever, and requested method
> message and send to objc_msgSend(), that function looks up the correct
> function pointer for the given reciever and method pair, if found it
> jumps there. If not found it can raise en exception, pass control to a
> "unhandled message" method, or silently ignore.
Putting aside performance, it looks to me that the main difference is
that Objective-C has good support for reflection. Maybe I'm wrong, but
I'd think better reflection (wherever it comes from) support would
enable to write the things you'd want to do in 'Objective-D' in D. Or
not? Excuse my ignorance of Obj-C.
More information about the Digitalmars-d
mailing list