Re: [Pyobjc-dev] AppKit/__init__.py complexity
Brought to you by:
ronaldoussoren
From: Bill B. <bb...@co...> - 2003-02-28 19:49:21
|
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 |