How do I extend a class that I never instantiate myself?

speeze.pearson at gmail.com speeze.pearson at gmail.com
Sat Oct 10 13:02:24 EDT 2015


(This is a long post, but the question is simple. Most of this is
just me enumerating what I've already tried.)

Someone wrote a library that creates and manipulates `Node`s.
I would like to write another layer on top of this, to make
trees that behave just like the library's trees, but whose nodes
have some extra methods.

"Subclass!" is the classic OO answer, and my first instinct.
Problem: I never instantiate `Node` myself. `Node`s are created
somewhere deep inside the library, and there's no way to tell it
"don't use `Node`, use this class instead."

Does anyone know a programming pattern that solves this problem?

(That's it! That's the question. Everything after this is
descriptions of solutions I'm not happy enough with.)

"Write a wrapper!" is my next instinct. Basically,

  class MyNode(object):
    ...
    def foo(self, *args, **kwargs):
      return self.node.foo(*args, **kwargs)
    def bar(self, *args, **kwargs):
      return self.node.bar(*args, **kwargs)
    ...

This would be tedious, but acceptable, if I knew how to make
`MyNode.parent` and `MyNode.children` return `MyNode`s
instead of `Node`s. Every way I've thought of makes me cringe:
- Make `MyNode` maintain its own parent/child info, and keep it
  in lock-step with the underlying `Node`'s parent/child info.
  Objection: this is a lot of work, and just begging to get out of sync.
- Give every wrapped `Node` a `_wrapper` attribute, specifying
  the wrapping `MyNode` instance. Then `MyNode.children` would
  return `[child._wrapper for child in self._node.children]`.
  Objection: it just feels weird adding custom attributes to objects.
- Have a global registry mapping `Node`s to their corresponding
  `MyNode` wrappers. Then `MyNode.children` would return
  `[MyNode.wrappers[child] for child in self.node.children]`.
  Objection: I've been trained not to like global state.

My last idea is that my approach is *entirely* wrong: I shouldn't
be trying to make the tree's nodes instances of my own class --
I should just use the existing library's `Node` class, and write
my library in a functional style. Don't define `MyNode.foo()`,
instead define `mylibrary.foo(my_node)`.
I've got nothing against functional programming, but mixing it
so closely with OO would, I think, result in a confusing,
schizophrenic interface.

Last possibly relevant fact: the library I want to extend is
`xml.dom.minidom`. By `Node` I mean `Element`, and the specific
methods I want to add will modify attributes used for CSS/JavaScript.


Thank you very much!
-Spencer



More information about the Python-list mailing list