Because a class can override isa to return what it wants, and you're bypassing that.
package MyIO;
sub isa
{
my $self = shift;
my $type = shift;
return 1 if $type eq 'IO::Handle';
return $self->SUPER::isa($type);
}
In this scenario, MyIO wants to claim to be an IO::Handle. That's perfectly allowed - presumably, then, it fulfills all the obligation of IO::Handle without actually deriving from it. Another example:
package MyNotIO;
use base 'IO::Handle';
sub isa
{
my $self = shift;
my $type = shift;
return 0 if $type eq 'IO::Handle';
return $self->SUPER::isa($type);
}
In this case, I don't want to look like an IO::Handle, even though I'm derived from it. Maybe I just want all the convenience of the IO::Handle type, while breaking its interface. Again, your UNIVERSAL::isa($obj, 'IO::Handle') would return incorrectly because it wouldn't be using this isa.
The problem with $fd->isa(...) is that it crashes if $fd is undef, whereas a simple "no" would be better. If they made that work at the same time as inheritance, that'd be awesome :-) Most likely, that would just be:
package UNIVERSAL;
sub safe_isa
{
my $obj = shift;
return unless defined $obj and ref $obj;
$obj->isa(@_);
}
Now you could call UNIVERSAL::safe_isa($fd, 'IO::Handle'), and it'd work properly, and safely, even if $fd wasn't actually an object. | [reply] [d/l] [select] |
my $answer = eval { $fd->isa(...) };
If it's not an object or isn't the right type, you get false. It doesn't matter to you why it is false because in both cases it's not the object type you are looking for.
| [reply] [d/l] |
use Scalar::Util 'blessed';
my $answer = blessed($fd) && $fd->isa(...);
which is better in that it allows you to stipulate that $fd is an object, not a class name.
| [reply] [d/l] |
| [reply] |
Thank you all for your answers!
Well then... I think I'll 'switch' to
$is_my_class = defined($object) && $object->isa('My::Class');
since I used to write
$is_my_class = defined($object) && $UNNIVERSAL::isa($object, 'My::Clas
+s');
or
$is_my_class = eval { $fd->isa('My::Class') };
to preserve my keyboard! ;)
@ Tanktalus: uh... I've never thought about this. But I think I... yeah... the time will come when I'll have to write a Decorator! At least this came to my mind when I read your post.
k | [reply] [d/l] [select] |
*narg*
Typo respectively wrong. I won't use
$is_my_class = defined($object) && $object->isa('My::Class');
because if $object is defined but not blessed...
I'll use
$is_my_class = eval { $fd->isa('My::Class') };
although normally (and I don't know why) I try to avoid 'eval'.
And although I'm not sure if I like this statement.
k | [reply] [d/l] [select] |
The documentation is wrong.
While the point another commenter made about can and isa being overridden is valid, that doesn't mean that you should never use them like that. Just that you should be really sure that that's what you want to do.
| [reply] [d/l] [select] |
my $isa = eval { $questionable->isa($class) };
| [reply] [d/l] [select] |
# checking whether argument is a subroutine reference
if (!UNIVERSAL::isa($callback, 'CODE')){
}
# popping last option parameter
my $options_ref = @_ && UNIVERSAL::isa($_[-1], 'HASH')? pop(): {};
| [reply] [d/l] |
If you are expecting a reference I would not recommend using UNIVERSAL::isa this way because the next one who has to deal with your code could believe that there is an object called 'HASH'. (Although this seems not to be very likely but I've seen worse things... :/ ).
If you want to check a reference I would advise you to keep using ref().
| [reply] |