Overriding a hard coded ISA module

X

xhoster

Is there an elegant way to tell other modules which are ISA some parent
(either directly or indirectly) that they should be ISA something else
instead?

For example, GD::Graph::lines, GD::Graph::points, and
GD::Graph::linespoints.pm are all subclasses of GD::Graph::axestype.

I want to subclass GD::Graph::axestype and override a method in it, and
have that override exist for the three end-use modules. Currently the way
I do it is to subclass each of the end-use modules individually:

package Xho::linespoints;
use base qw(GD::Graph::linespoints);
## GD::Graph is very buggy if numeric X axis are used
## without x_min_value and x_max_value being set.
## So set them to the pretty choice made by _best_ends
sub setup_x_step_size_v {
my $s=shift;
if ( defined $s->{x_tick_number}) {
$s->{x_min_value}=$s->{x_min} unless defined $s->{x_min_value};
$s->{x_max_value}=$s->{x_max} unless defined $s->{x_max_value};
};
$s->SUPER::setup_x_step_size_v;
};

## and likewise for other end-use modules.

Doing it this way isn't too awful, but it seems like there should be a
better way.

Thanks,

Xho
 
A

Anno Siegel

Is there an elegant way to tell other modules which are ISA some parent
(either directly or indirectly) that they should be ISA something else
instead?

Change their @ISA?
For example, GD::Graph::lines, GD::Graph::points, and
GD::Graph::linespoints.pm are all subclasses of GD::Graph::axestype.

I want to subclass GD::Graph::axestype and override a method in it, and
have that override exist for the three end-use modules. Currently the way
I do it is to subclass each of the end-use modules individually:

I'd try this (untested):

Make your own less buggy Xho::axestype:

package Xho::axestype;
use base 'GD::Graph::axestype';

sub buggy_method {
# your non-buggy override
}

1;

Then, before using GD::Graph, but after its @ISA is set up, do something
like this:

for ( \ (
GD::Graph::lines::ISA,
GD::Graph::points::ISA,
GD::Graph::linespoints::ISA,
) ) {
$_ eq 'GD::Graph::linespoints' and $_ = 'Xho::linespoints' for @$_;
}

That should make the three modules use your improved version. The
@ISA-modifying code could go in a CHECK- or INIT-block to make sure
everything is loaded when it is called.

Anno
 
A

Anno Siegel

Is there an elegant way to tell other modules which are ISA some parent
(either directly or indirectly) that they should be ISA something else
instead?

Change their @ISA?
For example, GD::Graph::lines, GD::Graph::points, and
GD::Graph::linespoints.pm are all subclasses of GD::Graph::axestype.

I want to subclass GD::Graph::axestype and override a method in it, and
have that override exist for the three end-use modules. Currently the way
I do it is to subclass each of the end-use modules individually:

I'd try this (untested):

Make your own less buggy Xho::axestype:

package Xho::axestype;
use base 'GD::Graph::axestype';

sub buggy_method {
# your non-buggy override
}

1;

Then, before using GD::Graph, but after its @ISA is set up, do something
like this:

for ( \ (
GD::Graph::lines::ISA,
GD::Graph::points::ISA,
GD::Graph::linespoints::ISA,
) ) {
$_ eq 'GD::Graph::linespoints' and $_ = 'Xho::linespoints' for @$_;
}

That should make the three modules use your improved version. The
@ISA-modifying code could go in a CHECK- or INIT-block to make sure[1]
everything is set up when it is called.

Anno

[1] Well, make it likely that everything is set up.
 
C

Ch Lamprecht

For example, GD::Graph::lines, GD::Graph::points, and
GD::Graph::linespoints.pm are all subclasses of GD::Graph::axestype.

I want to subclass GD::Graph::axestype and override a method in it, and
have that override exist for the three end-use modules. Currently the way
I do it is to subclass each of the end-use modules individually:

package Xho::linespoints;
use base qw(GD::Graph::linespoints);
## GD::Graph is very buggy if numeric X axis are used
## without x_min_value and x_max_value being set.
## So set them to the pretty choice made by _best_ends
sub setup_x_step_size_v {
my $s=shift;
if ( defined $s->{x_tick_number}) {
$s->{x_min_value}=$s->{x_min} unless defined $s->{x_min_value};
$s->{x_max_value}=$s->{x_max} unless defined $s->{x_max_value};
};
$s->SUPER::setup_x_step_size_v;
};

Hi,
I wrote a short example to find out how overriding of a method defined
in a baseclass can be done using multiple inheritance.
The code works, but I'm sure my approach to replace 'SUPER' is not the
best one ...

Any suggestions ??

Christoph


use warnings;
use strict;

package Root;
sub new{
my $class= shift;
my $self = {};
return bless $self ,$class ;
}
sub hello{
print "Root->hello\n";
}
sub say_hi{
print "Root->say_hi \n";
}

package Root_patch;
sub hello{
my $self = shift;
print "Root_patch->hello\n";
if (my $coderef = $self->find_next('hello')){
$coderef->($self,@_)
}
}
sub find_next{
# step through selfs @ISA and return the 1st method 'method_name'
# found after the one defined in the current package
my ($self,$method_name)= @_;
my $class = ref $self;
no strict 'refs';
my $get_this;
for my $parent(@{$class."::ISA"}){
if ($parent eq __PACKAGE__){$get_this = 1; next;}
if ($get_this && (my $code = $parent->can($method_name))){
return $code;
}
}
return undef;
}
package Child;
use base qw/Root_patch Root/;

package main;
my $instance = Child->new;
$instance->hello;
$instance->say_hi;

__END__
output:
Root_patch->hello
Root->hello
Root->say_hi
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top