How do you dynamically call a method of an object?

3.3k views Asked by At

in Perl I know you can use eval and *{$func_name} to call functions dynamically but how do you do this with methods of an object?

for example

EZBakeOven
  sub make_Cake { ... }
  sub make_Donut { ... }
  sub make_CupCake { ... }
  sub make_Soup { ... }

  sub make{
    my($self,$item) = @_;
    if( defined $self->make_$item ){ #call this func if it exists
      $self->make_$item( temp => 300, with_eggs => true ); 
    }
  }

so that if I say something like

$self->make('Cake');
#or maybe I have to use the full method name
$self->make('make_Cake');

it will call

$self->make_Cake();
2

There are 2 answers

4
CanSpice On BEST ANSWER

You should be able to do something like:

sub make {
  my ($self, $item) = @_;
  my $method = "make_$item";
  $self->$method(whatever);
}

Edit: You might want to also use can() to make sure you're calling a method that can be called:

sub make {
  my ($self, $item) = @_;
  my $method = "make_$item";
  if ($self->can($method)) {
    $self->$method(whatever);
  } else {
    die "No such method $method";
  }
}

Edit 2: Actually, now that I think about it, I'm not sure if you really can do that. Code I've written before does something like that, but it doesn't use an object, it uses a class (so you're calling a specific function in a class). It might work as well for objects, but I can't guarantee it.

0
fheyer On

As by @CanSpice suggested use can to check a methods existence in classes and objects. can returns a reference to the method if it exists, undef otherwise. You can use the returned reference to call the method directly.

The following example calls the method in package/class context. __PACKAGE__ returns the current package/class name.

if ( my $ref = __PACKAGE__->can("$method") ) {
    &$ref(...);
}