While thinking about generational garbage collection, the thought of generational interfaces occurred to me. I'd thought I'd run it by you guys. I'm curious if there are any examples of this out there.
I've opined on this chat room before that interfaces are more often cumbersome than helpful, especially in the early stages of a project where lots of refactoring is (or ought to be) happening. But as projects mature, interfaces do too, and that made me think interfaces could be generated automatically by monitoring the software over time. As an example, say I'm writing a flight simulator, and I have a abstract base class Airplane, that I want to have an interface someday, but I don't know what it is yet. So I define an AirplaneInterface = InterfaceTracker("Airplane") What this does is to open a sort of persistent database called Airplane (details aren't important now). The database tracks all objects that claim to implement the interface. So say the first airplane is a Piper Cherokee. I'd write a class like this: class PiperCherokeeX1(object): wingspan = 52.2 wingchord = 7.9 ... def __init__(self): self.x = 0.0 self.y = 0.0 self.z = 0.0 ... set_up_initial_state() ... AirplaneInterface.report(self) def move_stick(self,dx,dy): ... def move_thottle(self,ds): ... def move_rudder_pedals(self,ddr): ... def camera_matrix(self): return self._quat_to_matrix(self.q0,self.q1,self.q2,self.q3) def step(self,dt): ... The key here is the call to AirplaneInterface.report() at the end of __init__; this tells the interface tracker that, as of this call, this object is implementing the Aircraft interface. At this point, the interface tracker notes that PiperCherokeeX1 object has certain methods (move_stick, move_throttle, etc), certain class attributes, and certain instance attributes. And that's all it does-- at first. It just writes information into the database. As time passes, and development continues, methods and data are added, changed, reconfigured. For instance, I might split up move_stick() into move_stick_x() and move_stick_y() for some reason. Then I might get rid of these functions altogether in favor of a move_control(self,n,dx). And so on. I add more classes that implement the Aircraft interface, too. They look almost nothing like the original interface. However, through all that, the class attribute "wingspan" remains there. Until one day when the project is quite mature I add a new class, say Airbus380, that fails to define "wingspan". When this class calls AirplaneInterface.report(), it raises an InterfaceException. Basically, the InterfaceTracker decides, after some threshold of nearly universal usage of a certain method or attribute, that it has become a required part of the interface and starts raising exceptions when it's not there. Make sense? Details can vary, but that's the basic idea. In this way, you can combine some of the openness that helps in early development, but also have some of the benefits of stricter typing when things mature and turn out to be pretty strictly useful, without much effort. Thoughts? (Surely someone's thought to do this before.) Carl Banks -- http://mail.python.org/mailman/listinfo/python-list