On Friday, Feb 28, 2003, at 14:25 US/Eastern, Chris Ryland wrote:
> Can you expand on this thought a bit for a Cocoa/PyObjC newbie?
>
> I guess I'm not sure what the informal protocols are used for, and why
> they're interesting...
Sure -- "informal protocol" is really just a made up term that refers
to a collection of methods that fulfill some particular purpose. For
example, NSTableView has three informal protocols -- one for handling
of notifications, one for delegation, and one for the data source.
A formal protocol is like an interface in Java; a class that declares
compliance with a formal protocol or interface must implement all
methods in the protocol or interface.
An informal protocol typically has methods that are purely optional.
Some methods -- like a couple of the methods in the data source -- may
be required.
An example of an informal protocol:
@interface NSObject(NSTableViewDelegate)
- (void)tableView:(NSTableView *)tableView willDisplayCell:(id)cell
forTableColumn:(NSTableColumn *)tableColumn row:(int)row;
- (BOOL)tableView:(NSTableView *)tableView
shouldEditTableColumn:(NSTableColumn *)tableColumn row:(int)row;
- (BOOL)selectionShouldChangeInTableView:(NSTableView *)aTableView;
- (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(int)row;
- (BOOL)tableView:(NSTableView *)tableView
shouldSelectTableColumn:(NSTableColumn *)tableColumn;
- (void) tableView:(NSTableView*)tableView
mouseDownInHeaderOfTableColumn:(NSTableColumn *)tableColumn;
- (void) tableView:(NSTableView*)tableView
didClickTableColumn:(NSTableColumn *)tableColumn;
- (void) tableView:(NSTableView*)tableView
didDragTableColumn:(NSTableColumn *)tableColumn;
@end
In Objective-C, the above declaration is not backed by any
implementation. It is just a declaration mostly for the benefit of
the developer. If the above declaration were missing, it wouldn't
affect anything -- not at compile time, not at runtime.
The reason why we have to declare the methods in PyObjC is because of
the types.
Because methods like the above are typically implemented on some class
where none of the superclasses implement the method, then there is no
way for the PyObjC bridge to know that the 'row' parameter should be
handled as an (int) and not an (id).
Initially, you had to declare the types of the method when implementing
the method. I.e.:
def selectionShouldChangeInTableView_(self, aTableView):
return YES
selectionShouldChangeInTableView_ =
objc.selector("selectionShouldChangeInTableView:", signature="c@:@")
Obviously, that is very ugly. Instead, Ronald created the mechanism we
use today that allows you to declare that a class will be a target of
an informal protocol in this fashion:
class MyFooTableController(NSObject, NSTableDataSource,
NSTableViewDelegate):
def selectionShouldChangeInTableView_(self, aTableView):
return YES
This allows the PyObjC runtime to automatically deduce that
selectionShouldChangeInTableView_() really needs to return a BOOl or
that one of the methods that takes an (int) argument really wants an
(int) and not an object.
But there is an added benefit. Ronald added a feature to the informal
protocol creation mechanism such that you can mark a method as being
required.
As such, if you declare that an object will be implementing some/all of
the methods of an NSTableDataSource, the PyObjC bridge will
automatically determine if your class is compliant by checking to see
if you have implemented the one or two methods that are required if
your class is going to truly act as an NSTableDataSource.
b.bum
|