Python Notes

Friday, January 21, 2005

Inheritance in SQLObject

There's a debate going on about the best way to support inheritance in SQLObject. Better to have this discussion now than never; there is demand for this feature, but there's still no consensus on the best way to do it.

Based on a patch initially offered by Daniel Savard, Oleg Broytmann started last November and maintained a private inheritance branch, and got it working with some patches against the current trunk version. The approach is reminiscent of pure OO inheritance; you can define the base classes in SQLObject, and inherit new classes from them. There is some documentation about inheritance in the branch itself. For example:

class Person(SQLObject):
_inheritable = 1 # I want this class to be inherited
firstName = StringCol()
lastName = StringCol()

class Employee(Person):
_inheritable = 0 # If I don't want this class to be inherited
position = StringCol()

Ian Bicking offered this week a counterproposal, which is based on the relational interpretation of inheritance.

class Person(SQLObject):
firstName = StringCol()
lastName = StringCol()

class Employee(JoinedSQLObject):
_parent = 'Person'
position = StringCol()

The difference is subtle, but important. In Oleg's branch the child class is a descendent of the parent class, in pure OO terms. The resulting database schema contains two tables that are joined to build the child class implicitly. On the other hand, on Ian's proposal, two tables are explicitly created; all that the developer gets is some synctatic suger to simplify the declaration of the relationship between the parent and child classes.

For some reason, I like Ian's proposal better. It's more explicit, and it does not involve any magic or surprise as for the actual implementation. Also, porting between the two versions seems to be relatively easy. I'd like to see it implemented. On the other hand, Oleg's implementation had one interesting feature: it actually mapped, in transparent way, all the attributes of the parent class as attributes of the child class. I don't know if Ian intend to keep this behavior, that may have a lot of caveats of its own. But it seems logical, and makes acessing attributes on the child class easier, and more naturally related to the inheritance relationship, as shown in this example:

newemployee = Employee(firstName='John',
lastName='Smith',
position='Hardcore coder')

Errata

I had originally mistakenly attributed the inheritance patch to Oleg Broytmann. Ian Bicking has kindly pointed me to Daniel Savard as the original author (Thanks Ian!).

I had also missed an important semantic difference between the proposals. In the original proposal, a select done on the child table can return heterogeneous members; for example, a select on Employee by firstName may return both Person and Employee objects. Again, thanks to Ian for kindly pointing that out.

15 Comments:

Post a Comment

<< Home