libxml-raku / LibXML-raku

Raku bindings to the libxml2 native library
Artistic License 2.0
11 stars 5 forks source link

Simplify subclassing in complex cases #86

Closed vrurg closed 2 years ago

vrurg commented 2 years ago

If there is a need from a registered subclass to not just override an original LibXML:: class one-to-one, but map into a set of child classes depending on node's content (name, attribute value, etc.) then previously the only valid way was to override bless method because boxing were mostly done through LibXML::Node box method. Now it would be easier by inheriting from LibXML::Config and adding a custom class-from method.

See t/00subclass.t

vrurg commented 2 years ago

This is to simplify cases like the one with my work project where I want some simplistic parsing of SVG and want to have sub-classes based on node names. E.g. SVG::g, SVG::defs, SVG::path, etc.

Turns out, I over-optimized the box method by using configuration class-map method. While this is expected to provide a little gain comparing to use of class-from, but in order to achieve the desired subclassing I had to override method bless and do some trickery to avoid falling into a deep recursion, and so on.

Speaking of versions, this is a clear case of bumping api because config API has been slightly extended.

Another interesting note is about subclassing config. I do have certain misunderstandings with multi-dispatch sometimes. This was another case of the kind. I would expect

multi method class-from(::?CLASS:D: xmlElem:D $raw) {...}

to be sufficient for MyConfig class in 00subclass.t, but alas! Even though the candidate is more specific based on its self type and the positional type – it doesn't get called. Perhaps it is a side effect of OO::Monitors, but I just can't experiment right now. So, I chose full method overriding path.