jantimon
jantimon

Reputation: 38142

How can I check if an object has a specific method?

I want to use a method of an object. Like $myObject->helloWorld().

However there are a couple of methods so I loop through an array of method names and call the method like this:

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

This works quite nice but some objects don't have all methods.

How can I tell whether $myObject has a method called helloWorld or not?

Upvotes: 43

Views: 17180

Answers (4)

brian d foy
brian d foy

Reputation: 132720

The canonical way to use can is inside an eval block in case the thing that you have in your scalar variable isn't actually an object. You don't have to worry about that because you'll still get the right answer (a non-object or class can't respond to the method):

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

The can has the added feature that it returns a code reference to the method. Sometimes that can be handy.

Upvotes: 10

Thomas Wadley
Thomas Wadley

Reputation: 11

I used this method when checking database connections, passed into a function, such as

my $method = "ping";
if(defined ($local_dbh) && eval{ $local_dbh->can($method) } ) {
    if ($local_dbh->ping) {
        return $local_dbh;
    }
}
else {
    ## do connection
    ...
}

Upvotes: 1

DVK
DVK

Reputation: 129363

As Eric noted, you can usually use UNIVERSAL::can

It can be used either on an object as in your example ($obj->can($methodName)) or statically, on a class: (CLASS->can($methodName))

Please note that there are possible false negatives associated with using UNIVERSAL::can on objects/classes which have AUTOLOAD-ed methods - see the perldoc for details. So before using can() on an object/class, please be careful to verify that the class in question either does not use AUTOLOAD, or overrides can() to compensate, or uses forward declaration to compensate as described in can()'s perldoc - hat tip to brian d foy)

Also, please be careful to either ONLY call can() on actual objects, or encapsulate it in eval. It will die if called on a non-object (e.g. undef, scalar etc...)

Upvotes: 15

Eric Strom
Eric Strom

Reputation: 40142

You can use the UNIVERSAL::can method of all objects to determine what methods it supports:

if ($myObject->can($methodName)) {
    $myObject->$methodName;
}

Upvotes: 53

Related Questions