Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Perl Misc (http://www.velocityreviews.com/forums/f67-perl-misc.html)
-   -   Overriding a hard coded ISA module (http://www.velocityreviews.com/forums/t896624-overriding-a-hard-coded-isa-module.html)

xhoster@gmail.com 02-16-2006 06:47 AM

Overriding a hard coded ISA module
 
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

--
-------------------- http://NewsReader.Com/ --------------------
Usenet Newsgroup Service $9.95/Month 30GB

Anno Siegel 02-16-2006 11:03 AM

Re: Overriding a hard coded ISA module
 
<xhoster@gmail.com> wrote in comp.lang.perl.misc:
> 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
--
If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers.

Anno Siegel 02-16-2006 11:07 AM

Re: Overriding a hard coded ISA module
 
<xhoster@gmail.com> wrote in comp.lang.perl.misc:
> 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.

--
If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers.

--
If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers.

Ch Lamprecht 02-16-2006 10:23 PM

Re: Overriding a hard coded ISA module
 
xhoster@gmail.com wrote:

> 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
--

perl -e "print scalar reverse q/ed.enilno@ergn.l.hc/"


All times are GMT. The time now is 06:54 AM.

Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57