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