reference to object method

H

Hobo Salesman

Can I store a reference to an object method in a scalar and use that to
call the method? Something like (and I'm sure this is wrong):

$methodRef = \$object->method();
&{$methodRef}($argument);
 
X

xhoster

Hobo Salesman said:
Can I store a reference to an object method in a scalar and use that to
call the method? Something like (and I'm sure this is wrong):

$methodRef = \$object->method();
&{$methodRef}($argument);


my $ref = sub { $object->method(@_) };

$ref->($argument);

Xho
 
U

Uri Guttman

x> my $ref = sub { $object->method(@_) };

x> $ref->($argument);

much better to use UNIVERSAL::can:

my $meth = $obj->can( 'method_name' ) ;

$meth->( $arg ) ;

uri
 
B

Ben Morrow

Quoth Uri Guttman said:
x> my $ref = sub { $object->method(@_) };

Note that $object must be a lexical here, or the anon sub won't close
over it. (But it was anyway, of course... :) )
x> $ref->($argument);

much better to use UNIVERSAL::can:

my $meth = $obj->can( 'method_name' ) ;

$meth->( $arg ) ;

....except that just calls the method as a sub, i.e. the invocant is not
preserved. For that you need another closure, hence Xho's answer is the
simplest possible.

Ben
 
A

Anno Siegel

Uri said:
x> my $ref = sub { $object->method(@_) };

x> $ref->($argument);

much better to use UNIVERSAL::can:

my $meth = $obj->can( 'method_name' ) ;

$meth->( $arg ) ;

Ah, but these are not the same. The way I read the OP, the idea is to
freeze both the object and the method in a scalar, and that's what Xhos
solution does. Yours only catches the method, the object would still
have to be supplied as an argument.

Anno
 
U

Uri Guttman

GH> ^^^^^^^^^^^

GH> Why?

you don't need the extra complexity of a closure. why do something that
is not needed?

uri
 
U

Uri Guttman

AS> Ah, but these are not the same. The way I read the OP, the idea is to
AS> freeze both the object and the method in a scalar, and that's what Xhos
AS> solution does. Yours only catches the method, the object would still
AS> have to be supplied as an argument.

i read it as i answered it. we can agree the OP is somewhat ambiguous
there. i see reference to a method (found via an object). he seems to
have the object floating around and so it doesn't need to be stored in
the closure (and so the closure isn't needed). so the OP would need to
clarify this.

uri
 
X

xhoster

Uri Guttman said:
x> my $ref = sub { $object->method(@_) };

x> $ref->($argument);

much better to use UNIVERSAL::can:

Neat, I've never considered can to return more than a boolean.
my $meth = $obj->can( 'method_name' ) ;

$meth->( $arg ) ;

Doesn't that call the method as a regular subroutine, with $arg where $self
should be?

Wouldn't that need to be: ?
$obj->$meth($arg);

The anonymous sub method stores the object as a closure (well, as long
as it is a lexical, anyway), whereas the UNIVERSAL::can method requires you
to keep your hands on the object your own self. I thought that the point
of the OP was not to have to do that, but maybe I misread his point.


Xho
 
H

Hobo Salesman

Hobo said:
Can I store a reference to an object method in a scalar and use that to
call the method?

Thanks for the solutions. I don't have a specific application, I'm just
learning OOP and figuring out different ways to structure things.
THanks again.
 
M

Mumia W.

Hobo said:
Can I store a reference to an object method in a scalar and use that to
call the method? Something like (and I'm sure this is wrong):

$methodRef = \$object->method();
&{$methodRef}($argument);

The others have given you good methods of doing this including their
pros and cons. This method should avoid the need to lexicalize the
object as well as store all the data required to do a proper method call:

$callref = [ $obj->can('method') , $obj ];
$callref->[0]($callref->[1]);

You can make a sub to prettify the call site if you want to.

sub cR {
my ($sub, $obj, @arglist) = @_;
$sub->($obj, @arglist);
}

cR @$callref;

HTH
 
C

Ch Lamprecht

Uri said:
x> Doesn't that call the method as a regular subroutine, with $arg where $self
x> should be?

x> Wouldn't that need to be: ?
x> $obj->$meth($arg);

my bad. brain wasn't fully engaged. and i have used can like that a few
times so i should know how to call the method! your code is correct
there.

It will still call the method as a regular subroutine...
So maybe it should be better written as

$meth->( $obj,$arg );

Christoph
 
U

Uri Guttman

x> should be?
x> Wouldn't that need to be: ?
x> $obj->$meth($arg);
CL> It will still call the method as a regular subroutine...
CL> So maybe it should be better written as

CL> $meth->( $obj,$arg );

no, xhoster's fix of my bug is correct. your way skips inheritance.

$obj->$meth($arg);

uri
 
C

Ch Lamprecht

Uri said:
x> should be?
x> Wouldn't that need to be: ?
x> $obj->$meth($arg);

CL> It will still call the method as a regular subroutine...
CL> So maybe it should be better written as

CL> $meth->( $obj,$arg );

no, xhoster's fix of my bug is correct. your way skips inheritance.

$obj->$meth($arg);

uri
so does his:

#!/usr/bin/perl
use strict;
use warnings;

package Object;

sub new {
my $self = {};
bless $self;
}

sub method{
my $self = shift;
print "Object::method invoked on $self with args @_\n";
}

package DerivedObject;
our @ISA = qw/Object/;
sub new {
my $self = {};
bless $self;
}

sub method{
my $self = shift;
print "ObjectDerived::method invoked on $self with args @_\n";
}

package main;

my $object = Object->new;
my $object_derived = DerivedObject->new;

my $method_ref = $object->can("method");
my @args = qw/foo bar/;
for ($object, $object_derived, 'nothing'){
$method_ref->($_,@args);
$_->$method_ref(@args);
$_->method(@args);
print "\n";
}


Christoph
 
C

Ch Lamprecht

Ch said:
so does his:

Added the case you might be thinking of: ...??

#!/usr/bin/perl
use strict;
use warnings;

package Object;

sub new {
my $self = {};
bless $self;
}

sub method{
my $self = shift;
print "Object::method invoked on $self with args @_\n";
}

package DerivedObject;
our @ISA = qw/Object/;
sub new {
my $self = {};
bless $self;
}

sub method{
my $self = shift;
print "ObjectDerived::method invoked on $self with args @_\n";
}

package main;

my $object = Object->new;
my $object_derived = DerivedObject->new;

my $method_ref = $object->can('method');
my $method_name = 'method';

my @args = qw/foo bar/;
for ($object, $object_derived, 'nothing'){
$method_ref->($_,@args);
$_->$method_ref(@args); # function call
$_->$method_name(@args); # method call
$_->method(@args);
print "\n";
}


Christoph
 
A

Anno Siegel

Uri said:
x> should be?
x> Wouldn't that need to be: ?
x> $obj->$meth($arg);

CL> It will still call the method as a regular subroutine...
CL> So maybe it should be better written as

CL> $meth->( $obj,$arg );

no, xhoster's fix of my bug is correct. your way skips inheritance.

$obj->$meth($arg);

Same difference. Since $meth is a coderef inheritance doesn't enter
the equation.

Anno
 
C

Ch Lamprecht

Ben said:
Err, yes... presumably that's the point of taking a ref to a method?

Xho's fix is correct, your way is ugly :).

Just in case you are missing my point:

my $meth = $obj->can( 'method_name' ) ;

$meth wil now contain a coderef if 'method_name' was found.
According to perlref it would be called like:
&{$meth}($obj,$arg);
&$meth($obj,$arg);
$meth->($obj,$arg);

If you prefer to call it like so
$obj->$meth($arg);
I consider it to be misleading, because it looks like a method call without
being one. Someone reading that line might think, $meth contained a method-name...

Christoph
 
U

Uri Guttman

BM> Err, yes... presumably that's the point of taking a ref to a method?

yeah, the OP's original issue is long lost in my skull. and i bet he
isn't reading this thread anymore!

BM> Xho's fix is correct, your way is ugly :).

and your mother is fixed and also ugly too! :)

uri
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top