Как я могу проверить, есть ли у объекта определенный метод? - PullRequest
36 голосов
/ 15 апреля 2010

Я хочу использовать метод объекта. Как $myObject->helloWorld().

Однако есть пара методов, поэтому я перебираю массив имен методов и вызываю метод следующим образом:

my $methodName ="helloWorld";
$myObject->$methodNames;

Это работает довольно хорошо, но некоторые объекты не имеют всех методов.

Как я могу определить, есть ли у $myObject метод с именем helloWorld или нет?

Ответы [ 4 ]

47 голосов
/ 15 апреля 2010

Вы можете использовать метод UNIVERSAL::can для всех объектов, чтобы определить, какие методы он поддерживает:

if ($myObject->can($methodName)) {
    $myObject->$methodName;
}
13 голосов
/ 15 апреля 2010

Как заметил Эрик, вы можете обычно использовать UNIVERSAL::can

Может использоваться как на объекте, как в вашем примере ($obj->can($methodName)), так и статически, на классе: (CLASS->can($methodName))

Обратите внимание, что возможны ложные отрицания, связанные с использованием UNIVERSAL::can для объектов / классов, которые имеют методы AUTOLOAD-ed - подробности см. В perldoc . Поэтому перед использованием can() для объекта / класса, пожалуйста, убедитесь, что рассматриваемый класс либо не использует AUTOLOAD, либо переопределяет can() для компенсации, либо использует прямое объявление для компенсации, как описано в can() s perldoc - подсказка Брайану Дой Фой)

Кроме того, будьте осторожны, чтобы либо ТОЛЬКО вызывать can() на реальных объектах, либо инкапсулировать его в eval. Он умрет, если вызывается для необъекта (например, undef, скаляр и т. Д.)

9 голосов
/ 15 апреля 2010

Канонический способ использования can находится внутри блока eval на случай, если то, что у вас есть в вашей скалярной переменной, на самом деле не является объектом. Вам не нужно беспокоиться об этом, потому что вы все равно получите правильный ответ (не-объект или класс не могут ответить на метод):

 if( my $ref = eval { $obj->can( $method ) } ) {
      $obj->$ref( @args );
      }

can имеет дополнительную функцию, которая возвращает кодовую ссылку на метод. Иногда это может быть удобно.

1 голос
/ 09 апреля 2012

Я использовал этот метод при проверке соединений с базой данных, передаваемых в функцию, такую ​​как

my $method = "ping";
if(defined ($local_dbh) && eval{ $local_dbh->can($method) } ) {
    if ($local_dbh->ping) {
        return $local_dbh;
    }
}
else {
    ## do connection
    ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...