download version 0.1 view
source
Update: Bob Ippolito, on the PEAK mailing list, points out that I have it backwards. Objective-C classes can be modified by Categories without the class' consent. I still feel that the mechanism here is useful, although it probably shouldn't be called 'Categories' - expect a rename soon. Objective-C has a novel language feature called 'Categories'. Categories let you add new methods to a class in a consistent manner, without using inheritance. What Ruby calls 'modules' implement a similar feature. Python (or any other language besides Objective-C, AFAICT) doesn't have an equivalent, so while playing with the new decorator syntax in Python 2.4 last night, I implemented a simple Category mechanism for Python. First, the syntax, then some background and an example. class StringyThings(Category): @categorymethod def printUpperCase(self): print self.string.upper() class SomeStringyThing: @categories(StringyThings): def __init__(self, string): self.string = stringThe code above defines a category called StringyThings that has a printUpperCase method, and a class called SomeStringyThing that belongs to the StringyThings category. Categories let you define a named set of methods that can be attached to classes at runtime. Classes (and their subclasses) gain all the methods for the Categories they belong to, and acquire new category methods as they're defined. @category(StringyThings) def printLowerCase: print self.string.lower()Here, we've added a new method to the StringyThings category, called printLowerCase. Once the function definition is executed, all present and future instances of classes belonging to StringyThings (and their subclasses) gain the new method. The Pythonic idiom for grouping related methods that don't belong to any particular class is to use Mixin classes and multiple inheritance. Mixin classes are ugly - they carry the overhead of having an extra parent class and can make further extension of classes more difficult. A category feature eliminates the need for mixins by binding the category methods directly to the member class. This helps improve locality of reference ('you pay for every ".") for complex class hierarchies. You can also change a classes behavior for a different application domain by providing new category implementations. Categories have some similarity to the concept of Interfaces, but providing an actual implementation rather than a loose specification. They also have some neat side-effects. As long as your base class belongs to a category, you can change the behavior dynamically, at runtime. You can use this to fix bugs in other peoples code without having to write new classes. last change 2004-12-20 15:16:00 |
A novel little metaclass that mimics ObjC/NEXTStep "Categories". |
© 2004-2005, Andrew R. Gross