Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
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;
Comment on Pointers to member functions
Download Code
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.)

Back to Snippets Section

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: snippet [id://106214]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (10)
As of 2014-10-23 16:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (125 votes), past polls