Polymorphism and wrapping Python

Kirk McDonald kirklin.mcdonald at gmail.com
Sat Jun 3 01:29:24 PDT 2006


I'm currently writing a family of classes that wrap the object layers of 
the Python/C API. The class hierarchy looks something like this:

DPyObject
   DPyNumber
     DPyInteger
     DPyFloat
     (etc)
   DPySequence
     DPyString
     DPyList
     (etc)
   DPyMapping
     DPyDict
   (etc)

All of the classes on the second level are declared as "abstract," and 
(appropriately) represent the Python/C API's abstract objects layer. 
DPyObject and the classes on the third level are not abstract and 
represent the concrete objects layer. (Though I think I may eventually 
make DPyObject abstract, too.)

Behind this is a factory function that takes a PyObject* (the Python/C 
API's usual way of representing a Python object) and returns a instance 
of the proper subclass of DPyObject.

I have a question, then, of polymorphism, and how closely I should try 
to emulate Python.

In Python, if you try to (for example) add two instances of a class that 
doesn't have the __add__ method (Python's equivalent of opAdd) defined, 
Python will raise a TypeError. If you try to do this in D, it is a 
compile-time error.

At the moment, DPyObject doesn't define opAdd. DPyNumber does, like this:

DPyNumber opAdd(DPyNumber rhs) {
     return make_dpyobject(PyNumber_Add(m_ptr, rhs.m_ptr));
}

(If you're unfamiliar with the Python/C API, PyNumber_Add takes two 
PyObject* arguments and returns a new PyObject* with the result. m_ptr 
is the only member of DPyObject, and is a PyObject*. make_dpyobject is 
my factory function that returns the proper subclass of DPyObject based 
on the type of the PyObject* passed to it.)

If we have:

DPyObject o = new DPyInteger(5);
DPyObject p = new DPyInteger(10);
DPyObject q = o + p; // Error! DPyObject doesn't define opAdd.

I'm trying to decide if this is a problem. I can easily define this for 
DPyObject:

DPyObject opAdd(DPyObject rhs) { assert(false); }

Then the above example would work, but I'm not totally sure that this is 
desirable behavior. In Python it certainly would be: that language is 
all about the duck typing. It would certainly simplify the API, in that 
all DPyObject-derived classes would have the same interface (now there's 
an idea, I should write an interface...). But I still have this 
irrational fear that it is a bad idea.

Anyone have more insight than I can currently muster?

-Kirk McDonald



More information about the Digitalmars-d mailing list