Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Pointers to member functions

by ariels (Curate)
on Aug 20, 2001 at 17:28 UTC ( #106214=snippet: print w/replies, xml ) Need Help??
Description: Remember ::* and ->* from C++? If you do, you probably hate them.

A pointer to a member function lets you store a particular method in a variable and then apply it to objects. Here's how to get them in Perl.

It's a bit long, but almost all of it isn't code...

# Perl "pointer to member function" abstraction

package PMF;

use strict;
use Carp;

sub new {
  my ($class,$name) = @_;
  $name =~ /^[A-Za-z0-9_]\w*$/ or croak "Bad method name \"$name\"";
  bless eval <<"END_CODE", $class;
    sub {
      my \$self = shift;
      \$self->$name(\@_)
    }
END_CODE
}

sub call {
  my $self = shift;
  $self->(@_)
}


package PMF::able;

sub call {            # permute our args
  my $self = shift;
  my $pmf = shift;
  $pmf->($self,@_);
}



=head1 NAME

PMF - pointer to member function in Perl

=head1 SYNOPSIS

    my $p = PMF->new('print');
    my $x = ClassWithPrintMethod->new(17);
    $p->($x, 'foo');           # call $x->print('foo')
    $p->call($x, 'foo');       # call $x->print('foo') in another way

    package MyClass;
    use vars qw/@ISA/;
    @ISA = qw/PMF::able/;
    # ...

    package main;
    my $y = MyClass->new('xyz');
    $y->call($p, 42);          # call $y->print(42)

=head1 DESCRIPTION

C<PMF> gives you pointers to member functions.  A PMF is the
abstraction of calling a particular method of an object, similar to
the C<::*> / C<-E<gt>*> mess of C++.

To create a PMF, pass C<new> the name of the method you want to
call. C<PMF::new> creates a code object that calls that method of any
object (contrast C++ pointers to member functions, which are
restricted to subclasses of some root class).  Lacking a better
dispatch syntax, you apply a PMF C<$pmf> to an object C<$obj> by
saying C<$pmf-E<gt>($obj, I<args...>)>.

=head1 ALTERNATE CALLING SYNTAX

If you would rather say C<$obj-E<gt>call($pmf, I<args...>)>, you need
to make the class of C<$obj> inherit from the mixin class
C<PMF::able>, which provides exactly this C<call> method.

If you wish to avoid changing the class of C<$obj>, you can still use
the alternate syntax by creating your objects in an appropriate dummy
class:

    package MyClass2;
    use vars qw/@ISA/;
    @ISA = qw/ClassWithPrintMethod PMF::able/;
    # empty package body!

    package main;
    my $z = MyClass2->new(19);
    $z->call($p, 'foo');

=head1 NOTES / BUGS

=over 4

=item *

A PMF is not really an object.  It I<is> blessed into the class
C<PMF>, but has no methods except C<call>!

=item *

The syntax is horrible.  At least it is not as bad as in C++.

=item *

C<PMF::able> is probably more confusing than useful.

=head1 AUTHOR

Ariel Scolnicov C<E<lt>ariels@compugen.co.ilE<gt>>

=cut


1;
Replies are listed 'Best First'.
Re: Pointers to member functions
by japhy (Canon) on Aug 20, 2001 at 18:55 UTC
    What about:
    $meth = $obj->can($method_name); $meth->($obj, @args);

    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker.
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

      Also note that using a function reference with the method syntax works just fine. Consider the following example where an unnamed method is called from an object in a class with no methods of its own:
      my $foo = bless {}, "bar"; my $meth = sub {shift; print shift}; $foo->$meth("Sneaky");
      (Yeah, I know you know that, but others might find it neat.)
Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: snippet [id://106214]
help
Chatterbox?
[ambrus]: Today I accidentally cut my hand while carrying a computer. On the display part of the motherboard that sticks out at the back of the chasis and has ports, there's this thin metal sheet with holes cut for the ports, to guide plugs into the sockets.
[ambrus]: This sheet has sharp needle-like parts, 0.004 long and less than 0.001 wide, that can get bent to point outwards, and one of these cut into my palm when I lifted the box.
[ambrus]: So now when I choose what motherboard to buy for my new home computer, I have one more specific property to guide me. Useful, because there's so many different boards to choose from.

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (7)
As of 2017-01-16 19:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Do you watch meteor showers?




    Results (151 votes). Check out past polls.