Subject: | Implementation of as_HTML makes it effectively impossible to subclass |
I want to subclass HTML::Element as HTML::Element::Table, including most
of the functionality of Stacy Lacy/Anthony Peacock's HTML::Table in it.
I've add HTML::Table as a mixin, and I reckoned all I needed to do was
override 'new' and 'as_HTML' (and a couple of other traversal methods
that I haven't looked at yet) and add an AUTOLOAD to pass on
HTML::Table's methods to it.
That worked fine until I tried to output a structure which had
HTML::Element::Table objects inside it. I found that my overridden
as_HTML table was not being called.
Looking at the source, I can see why: as_HTML uses 'traverse' whose
comment lovingly explains that it iterates instead of recursing.
Furthermore, I can't even override the callbacks, because they are
inline (and anyway, are not called as methods).
THIS BREAKS OBJECT INHERITANCE because there is nothing there for me to
override. If the callbacks were package methods, it would be much
messier, but I could override them; but as it is, it won't even work to
override as_HTML with a slightly altered copy of itself, as I can't get
my version to be called unless I happen to pass it one of my objects as
the root of the tree.
Note that what I am trying to do is compliant with the NOTES ON
SUBCLASSING at the end of the pod: my overridden method does call the
superclass method (or did until I tried the approach I mentioned in the
previous paragraph).
But because this has been done in this way, I can't see any way of
bolting the extra functionality on without changing HTML::Element.pm
itself. If at least the calls to $c_pre and $_post were changed to
$rv - $c_pre->(
$this->beforeTraverse(), ....
and
$rv = $c_post->(
$this->afterTraverse(), ....
(and the supplied 'beforeTraverse' and 'afterTraverse' just returned
their first argument), then at least I could override 'beforeTraverse'
to turn my table into element contents. This would mean an extra call,
but it's not recursing.