APM: Deprecated Inheritance problem
Tim Peoples
tpeoples at dmotorworks.com
Wed Dec 3 16:03:38 CST 2003
What happens if, in your derived class, you do the "use Tpwrap" *before*
the "use base ..." ??
(...just thinking outloud...)
Tim.
On Wed, 2003-12-03 at 15:46, Brian Michalk wrote:
> Here's the error I'm getting:
>
>
> Use of inherited AUTOLOAD for non-method Tpwrap::set_height_inches() is
> deprecated at /mnt/functions/develop/bin/der_vnet_tp.pm line 582
> (#2)
>
> (D deprecated) As an (ahem) accidental feature, AUTOLOAD subroutines are
> looked up as methods (using the @ISA hierarchy) even when the
> subroutines
> to be autoloaded were called as plain functions (e.g. Foo::bar()),
> not as methods (e.g. < Foo-bar() >> or < $obj-bar() >>).
>
> This bug will be rectified in Perl 5.005, which will use method lookup
> only for methods' AUTOLOADs. However, there is a significant base
> of existing code that may be using the old behavior. So, as an
> interim step, Perl 5.004 issues an optional warning when non-methods
> use inherited AUTOLOADs.
>
> The simple rule is: Inheritance will not work when autoloading
> non-methods. The simple fix for old code is: In any module that used
> to
> depend on inheriting AUTOLOAD for non-methods from a base class named
> BaseClass, execute *AUTOLOAD = \&BaseClass::AUTOLOAD during startup.
>
> In code that currently says use AutoLoader; @ISA = qw(AutoLoader); you
> should remove AutoLoader from @ISA and change use AutoLoader; to
> use AutoLoader 'AUTOLOAD';.
>
> Can't locate auto/Tpwrap/set_height_.al in @INC (@INC contains: blib/arch
> blib/lib /mnt/functions/develop/bin /samba/functions/develop/bin
> /root/bin c:/Vamos/programs/perl/lib /mnt/despav/samba/functions/develop/bin
> c:/Vamos/programs/perl/bin . /usr/lib/perl5/i386-linux /usr/lib/perl5
> /usr/lib/perl5/site_perl/i386-linux /usr/lib/perl5/site_perl) at
> /mnt/functions/develop/bin/der_vnet_tp.pm line 582 (#3)
> Uncaught exception from user code:
> ...
>
> What I have is a base class that I designed to be used by many other
> classes. It is supposed to initialize calibration variables, and if a
> command (from the command ethernet socket) is issued to initialize a
> variable it doesn't know about, it gives up and sends it to the derived
> class for processing. I hope I can summarize without too much code bloat.
>
> package base_class;
>
> ...
> sub set_cmd_keys { # associate a command with a subroutine reference
> my $self = shift;
> my $ref_subroutine = shift;
> my $varname = shift;
>
> $self->{keys}{cmd}{$varname}{ref_sub} = $ref_subroutine;
> }
>
> sub get_cmd_sub { # returns the subroutine reference associated with
> setting/getting value for a variable
> my $self = shift;
> my $varname = shift;
>
> if (defined $self->{keys}{cmd}{$varname}) {
> if (defined $self->{keys}{cmd}{$varname}{ref_sub}) {
> return $self->{keys}{cmd}{$varname}{ref_sub};
> }
> }
> return undef;
> }
> ...
> sub process_command_data {
> my $self = shift;
> ... lots of variables here
>
> $self->get_command_lines();
> while (@{$self->{incoming}{command}}) {
> ... whittle down to a single command, key, value
> # for this email, set the parameters manually
> $cmd = "LASER_HEIGHT";
> $key = "5FT";
> $val = undef;
> $ref_sub = $self->get_cmd_sub($cmd); # check to see if a subroutine
> reference was ever stored for this command
> if (defined $ref_sub) { # if a reference was stored, call that
> subroutine
> my $message = $self->$ref_sub($key, $val);
> $self->send_cmd_socks($message); # send the results of the command
> } else {
> ... # process generic commands
> }
> }
> }
>
> package derived_class;
>
> use base base_class; # inherit everything from the base class
> use Tpwrap; # this is an XS module that uses a C library to talk to
> the laser device driver
>
> sub init {
> my $self = shift;
> $self->set_cmd_keys($self->can("set_laser_height"), 'LASER_HEIGHT'); #
> associate a reference to a subroutine
> Tpwrap::init(); # works just fine
> }
> ...
> sub set_laser_height {
> my $self = shift;
> if (@_) {
> my $t = shift;
> $self->{laser_laser_height} = $t;
> Tpwrap::set_height_inches($t);
> #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This is where the problem is
> }
> return $self->{laser_laser_height}.'IN';
> }
>
>
> I think the problem is that set_laser_height is getting called in a context
> from the base class, and of course the base class doesn't know anything
> about Tpwrap.
>
> Any help/comments?
>
> _______________________________________________
> Austin mailing list
> Austin at mail.pm.org
> http://mail.pm.org/mailman/listinfo/austin
--
Tim Peoples <tpeoples at dmotorworks.com>
CTG
More information about the Austin
mailing list