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
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |