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.
Re:This is also an API problem
chromatic on 2006-01-24T22:33:07
What if
$object
contains a class name?Re:This is also an API problem
jk2addict on 2006-01-24T22:50:16
Then return true. It's not telling a lie.
$classname->foo and &classname::foo exists, and can be called. How they are supposed to be called is up to the module author and consumer, and not the concern of can.Re:This is also an API problem
chromatic on 2006-01-25T03:11:38
I simply mean that there isn't a single use for
UNIVERSAL::can
that makes a replacement easy to write.UNIVERSAL::isa
is even worse.
withUNIVERSAL::can($object, 'method')
. It Just Works.eval { $object->can('method') }
Re:Simpler means
Alias on 2006-01-25T01:16:06
Unless ->can throws an exception, in which case you get a false negative...
I really need to get around to adding _CAN to Params::Util:/
Re:Simpler means
merlyn on 2006-01-25T01:33:10
well, if it threw an exception, it probably can't do that then. {grin}