Как вы динамически вызываете метод объекта?

В Perl я знаю, что вы можете использовать eval и *{$func_name} для динамического вызова функций, но как вы делаете это с методами объекта?

например

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 ); 
    }
  }

так что если я скажу что-то вроде

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

это позвонит

$self->make_Cake();

2 ответа

Решение

Вы должны быть в состоянии сделать что-то вроде:

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

Изменить: вы также можете использовать can() чтобы убедиться, что вы вызываете метод, который можно вызвать:

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

Редактировать 2: На самом деле, теперь, когда я думаю об этом, я не уверен, что вы действительно можете это сделать. Код, который я написал ранее, делает что-то подобное, но он не использует объект, он использует класс (так что вы вызываете определенную функцию в классе). Это может сработать и для объектов, но я не могу этого гарантировать.

Как @CanSpice предложил использовать can проверить существование методов в классах и объектах.can возвращает ссылку на метод, если он существует, иначе undef. Вы можете использовать возвращенную ссылку для непосредственного вызова метода.

В следующем примере метод вызывается в контексте пакета / класса. __PACKAGE__ возвращает имя текущего пакета / класса.

if ( my $ref = __PACKAGE__->can("$method") ) {
    &$ref(...);
}
Другие вопросы по тегам