Pseudo-Cocoa Delegation Pattern With REALbasic
If you’ve ever done any programming with Cocoa, you’ll notice fairly quickly that the dynamic runtime offered by Objective-C has some serious advantages over traditional function calls. The Objective-C runtime operates with a concept of messages being sent to objects. These objects can then handle these messages in any way they choose. A good example of how this is useful is in the Cocoa delegation design pattern. When you want to customize an object, you don’t usually need to subclass it. Instead, you simply provide a delegate to the object that will handle customization. Delegates in REALbasic are basically function pointers, but in Cocoa, a delegate is an object which responds to certain messages on behalf of another object.
When programming on the iPhone, for example, you may place a UITableView into the window. This would be like placing a Listbox onto a REALbasic window. In REALbasic, you actually are creating a subclass, named Listbox1 by default. In Cocoa, however, you’re placing a UITableView object onto the window. So, how does loading the data into the “list” differ between Cocoa and REALbasic? Well, in REALbasic, since you have placed a subclass into the window, you simply respond to the necessary events, and call methods such as AddRow on the Listbox subclass. In Cocoa, you assign a “delegate” object which will respond to several messages sent by the UITableView when it needs to load data. The UITableView will “ask” the delegate how many rows of data there will be in the list. Then it asks for enough data to fill the visible area of the list. The benefit to this model is that the list only needs to be populated with enough data that can actually be seen. In REALbasic, you must add all the data to the list, even if the data will never be seen by the user. This can waste processing time, which can cause the user experience to be slow and non-responsive.
How can you fix this then? You could use Interfaces to create a delegation model, but then the object which is acting as the delegate would need to specifically implement the entire interface. In Cocoa, you can choose to implement at least the “required” methods and several of the “optional” methods. REALbasic doesn’t have an “optional” way to implement methods. Sure, you can just choose to fill in only some of the interface methods, but that means that you have to go through the process of choosing, ahead of time, to implement the interfaces. That also means that your code is not as separated since the interface must be explicitly declared and the implementor must explicitly implement the interface. It isn’t as “dynamic” as the Cocoa methodologies.
So, we can mimic the loose binding of methods by using the “Extends” keyword, and then optionally implementing the methods in various objects. Look at this Module:
Module MyOptionalDelegateModule
Function numberOfRowsInTable( Extends tableView As Object ) As Integer
// Do nothing here except return a “default” value
Return 0
End Function
End Module
Now, in your “pretend” delegate object, you can declare this method:
Class MyDelegateObject
Function numberOfRowsInTable() As Integer
// Here do the actual work
Return 5
End Function
End Class
Now, you could create a custom listbox which asks a “delegate” for some number of rows. You can assign any object as the delegate, even if it doesn’t implement “Function numberOfRowsInTable() As Integer” because the implementation in the module will be called. If the object does implement the method, its implementation will be called instead. So, you can define a bunch of methods and attempt to call them, and if the object actually implements the method, you’ll get the customized behavior.
So, if you like the delegation design pattern in Cocoa, you can now mimic it using the Extends feature of the REALbasic language. Protocols can already be mimicked simply by defining an Interface.