I want to subclass a class that I don't really control, as its objects are created by an other class, and I am looking for the best way to do this.

Here is the problem: in XML::Twig you create an XML::Twig object, and use it to parse XML data. During the parsing the XML::Twig object creates objects, in the XML::Twig::Elt class, for each element in the XML. It is easy to subclass XML::Twig, and add methods to it. It is however more difficult to subclass XML::Twig::Elt, as the objects are created within XML::Twig. It would be really convenient though, as you can define handlers on XML elements that are passed the element (in $_).

So I plan to add an elt_class option, that will let you write something like this:

my $t= XML::Twig->new( elt_class => 'my_elt_class', p => sub { $_->cut # an XML::Twig::Elt +method ->my_process; # a my_elt_class met +hod } ); package my_elt_class; BEGIN { @my_elt_class::ISA=('XML::Twig::Elt'); } # to inherit from XML +::Twig::Elt sub my_process { my $elt= shift; # stuff here }

So I have 2 questions: does this make sense? I know I like it, I was getting quite uncomfortable adding methods directly in the XML::Twig::Elt package all the time. And the second part: is the implementation below the best possible?

# in XML::Twig, every time it needs to create an element $self->{elt_class} || 'XML::Twig::Elt'; my $element= $elt_class->new;

Here is a complete example, which creates a default element, then element from classes that redefine the new and print methods, just the print method, and then nothing, inheriting both from XML::Twig::Elt.

#!/usr/bin/perl -w use strict; foreach my $elt_class ( '', 'my_elt1', 'my_elt2', 'my_elt3') { warn "testing $elt_class"; my $t= XML::Twig->new( elt_class => $elt_class); my $e= $t->add_elt; $e->print; } package XML::Twig; sub new { my $class= shift; return bless { @_ }; } sub add_elt { my $self= shift; $self->{elt} ||= []; # this is where it all happens my $elt_class= $self->{elt_class} || 'XML::Twig::Elt'; my $e= $elt_class->new; push @{$self->{elt}}, $e; return $e; } package XML::Twig::Elt; sub new { my $class= shift; warn " new elt $class in XML::Twig::Elt\n"; return bless { @_ }, $class; } sub print { print " printing from XML::Twig::Elt\n"; } # redefines new and print package my_elt1; # the BEGIN is needed or @my_elt1::ISA would not actually be initializ +ed BEGIN { @my_elt1::ISA= qw(XML::Twig::Elt); } sub new { my $class= shift; warn " new my_elt1 in my_elt1\n"; return bless { @_ }, $class; } sub print { print " printing from my_elt1\n"; } # redefines print (new is inherited) package my_elt2; BEGIN { @my_elt2::ISA= qw(XML::Twig::Elt); } sub print { print " printing from my_elt2\n"; } # does not redefine anything, both new and print are inherited package my_elt3; BEGIN { @my_elt3::ISA= qw(XML::Twig::Elt); }

In reply to OO Perl: subclassing a class through an other one by mirod

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.