Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask

Re: reference to a subroutine inside a package

by Stevie-O (Friar)
on Jun 03, 2004 at 02:07 UTC ( #359880=note: print w/replies, xml ) Need Help??

in reply to reference to a subroutine inside a package

As others have said, this sort of thing:
package Foo; sub foo(); sub new { bless[] } package Bar; our @ISA = qw(Foo); sub new { bless[] }
does not actually put a 'foo' method into Bar. Instead, when you do this:
$b = new Bar; $b->foo();
Perl calls an internal function called call_method() documented in perlapi to call $b->foo(). call_method() does this:
  1. Looks in the package the object is blessed into for a sub with that name. If one is found, great! That sub is called.
  2. Otherwise, recursively searches packages listed in @ISA for the given sub. If the sub is found, it is called.
  3. Otherwise, checks the magic UNIVERSAL package for the method. (Note that UNIVERSAL is only magic for call_method; you can add new global object methods by adding them to the UNIVERSAL package!)
  4. Failing that, the blessed object's package and its @ISA are scanned again; however, instead of looking for the specified method, it looks for a method named AUTOLOAD. (This can interfere when you want to use autoloaded methods, and you inherit from a class that uses autoloaded.) Note that UNIVERSAL::AUTOLOAD will be called if it exists.
  5. If Perl finally gets to this step, your program will croak with "Can't locate object methd 'foo' via package 'Bar' at...".

Note that this mechanism plays funnily with things that work by placing specially named methods into packages (specifically, overloading).

Now with that explanation out of the way, there are two ways you can get at that method.

The first one was given by someone else:

$sub = $obj->can('foo'); # $sub references the sub that would be called if you # called $obj->foo(), handling inheritance and everything. # In fact, Perl has enough magic that if everyone plays # their cards right, it will work for autoloaded methods # that haven't even been loaded yet. # ...a bit later... # $obj->$sub(@args); # same as $obj->foo(@args);
If you really need a reference to the method, that's the only way to do it.

However, there's another alternative that has mysteriously vanished from the perl 5.8 documentation (it was present in 5.6); if you only care about the method itself, not the address, this will work equally well:

$meth = 'foo'; $obj->$meth(@args); # same as $obj->foo(@args)
$"=$,,$_=q>|\p4<6 8p<M/_|<('=> .q>.<4-KI<l|2$<6%s!<qn#F<>;$, .=pack'N*',"@{[unpack'C*',$_] }"for split/</;$_=$,,y[A-Z a-z] {}cd;print lc

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://359880]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (13)
As of 2017-02-27 13:54 GMT
Find Nodes?
    Voting Booth?
    Before electricity was invented, what was the Electric Eel called?

    Results (385 votes). Check out past polls.