Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Ovid (2709)

Ovid
  (email not shown publicly)
http://publius-ovidius.livejournal.com/
AOL IM: ovidperl (Add Buddy, Send Message)

Stuff with the Perl Foundation. A couple of patches in the Perl core. A few CPAN modules. That about sums it up.

Journal of Ovid (2709)

Tuesday January 24, 2006
04:54 PM

UNIVERSAL::can($don't, $do_this);

[ #28454 ]

I get awfully tired of writing this:

use Scalar::Util 'blessed';

if ( blessed($thing) && $thing->can('do_something') ) { ... }

Which is why I'm awfully tempted to just write this almost throwaway code and put it on the CPAN. I probably won't, but I toy with the idea.

package Can;

use strict;
use warnings;
use Scalar::Util 'blessed';
use base 'Exporter';
@EXPORT = 'Can';

sub Can {
  my ($object, $method) = @_;
  return unless blessed $object;
  return $object->can($method);
}

1;

And in my code:

use Can; # use Can () if you don't want importing

if ( Can( $thing, 'do_something' ) ) { ... }

Depending upon the type of code you write, it's quite easy to get an unblessed reference instead of an object. I get tired of always having to use blessed from Scalar::Util, but this is a common enough practice (I hit a lot in exception handling, for example) that it seems like a "write it and forget it" module might be useful.

And for those who do UNIVERSAL::can($object, $method), don't. If the object overrides &can, you're in trouble. If you already know your objects don't override &can, then you're relying on implementation details that you shouldn't be relying on.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • I admit it. I'm guilty of UNIVERSAL::can($object, $method). Been there. Done than. Changed them when I run across them in old code. My real beef with UNIVERSAL::can($object, $method) is one of usibility. What couldn't that have just made that method DTRT and simply return false/0 if $object wasn't an object at all. After all, in a sub as simple as this, I just want a true/false. No need to throw errors. It either can, or can't, regardless os whether $objectis or isn't an object.
  • I'm universally replacing
    UNIVERSAL::can($object, 'method')
    with
    eval { $object->can('method') }
    . It Just Works.
    --
    • Randal L. Schwartz
    • Stonehenge