One option is to use an anonymous sub:
package Resources;
my $my_class = new MY_CLASS;
our $resource = { '/list' => sub { $my_class->list_files(@_); } };
...
package main;
# dereference the code ref
&{$Resources::resource->{'/list'}};
# or call it:
$Resources::resource->{'/list'}();
Should you change what $my_class
references, it will also be changed in the anonymous function. This may be what you want; if not, keep reading for a function (bindMethod
) that binds an object and a method.
If you don't want the anonymous function to appear on the stack:
our $resource = { '/list' => sub { unshift @_, $my_class;
goto &MyClass::list_files; } };
Note that this form of goto
isn't the usual goto statement—it's a tail call.
You could define a helper method to set up the binding, though honestly it doesn't gain you much.
sub bindMethod {
my ($obj, $meth) = @_;
return sub { unshift @_, $obj; goto &{$meth}; }
}
my $my_class = new MyClass;
our $resource = { '/list' => bindMethod($my_class, \&MyClass::list_files) };
Here's a version of bindMethod
that doesn't require the class to be specified with the method name.
sub bindMethod {
my ($obj, $meth) = @_;
if (! ref $meth) {
my $class = ref $obj;
$meth = \&{"${class}::$meth"};
}
return sub { unshift @_, $obj; goto &{$meth}; }
}
...
my $my_class = new MyClass;
our $resource = { '/list' => bindMethod($my_class, 'list_files') };