[Python-3000] Abilities / Interfaces

Bill Janssen janssen at parc.com
Thu Nov 23 00:21:03 CET 2006


> On 11/22/06, Bill Janssen <janssen at parc.com> wrote:
> > Something like
> >
> >   class MyNewClass (ExistingClass, OtherInterfaceIJustNoticedExistingClassImplements):
> >     pass
> 
> No, unless you can also patch up all code that creates ExistingClass
> instances. You alluded to this before and it sounded like you didn't
> think it was an issue. Why do you think that? I see it as a huge
> problem when retrofitting pre-existing third-party code.

I don't think the specific issue raised above is very important (wow,
I just noticed that type A also implements the equivalent of interface
B, so I wish I could treat A as a B, but darn it, I can't since it
didn't inherit from B).  I think that ad-hoc adapter classes work OK
for handling that rare and incidental case, in the extremely rare case
that it *has* to be handled.

Not to say that there aren't interesting problems, though I'm not sure
just how "big" they are.  The biggest issue I see is the factory
problem.  The other is the existing value problem, which is a variant
on either the above or the factory problem.

Factory problem: This is a known OO problem.  You're given a factory,
which produces instances of type A.  You've got B, which is a subtype
of A, and you wish the factory would return that, since nobody who
knows anything uses A instead of B anymore.  You've got a number of
options: (1) change the factory to produce B instead of A; (2) wrap
each instance of A in a B which forwards A's methods to the original
instance; (3) somehow change the instance of A into an instance of B.

(1) is often practically not possible, though it's probably the right
thing to do.  In fact, "factories" should always be built to be
extensible (that is, they should be built so that user code can
register a new factory if desired).  (2) is always possible, but takes
some extra coding.  It would be nifty if Python could have a standard
way of doing (3).  That's what I'd aim for.  That would solve all
three of these related problems.  Notice, however, that (2) and (3)
would probably look pretty much the same for the practicing
programmer:

    myB = coerce_to_B(factory.produce_A());

(3) is practically speaking only possible for types which have
relatively independent initializers.

Is munging __bases__ so terrible?  Isn't it just:

  def ensure_base (i, clss):
    if not isinstance(i, clss):
        class X (i.__class__, clss):
            pass
        i.__class__ = X
        clss.__init__(i)
    return i

Would be nice to have anonymous classes :-).


Bill



More information about the Python-3000 mailing list