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