Recipe 13.9 Determining Subclass Membership
13.9.1 Problem
You want to know whether an object
is an instance of a particular class or that class's subclasses.
Perhaps you want to decide whether a particular method should be
invoked on an arbitrary object.
13.9.2 Solution
Use methods from the special UNIVERSAL class:
$obj->isa("HTTP::Message"); # as object method
HTTP::Response->isa("HTTP::Message"); # as class method
if ($obj->can("method_name")) { .... } # check method validity
13.9.3 Discussion
Wouldn't it be convenient if all objects were rooted at some ultimate
base class? That way you could give every object common methods
without having to add to each @ISA. Well, you can.
You don't see it, but Perl pretends there's an extra element at the
end of @ISA—the package named UNIVERSAL.
UNIVERSAL has only a few predefined methods, although you are free to
add your own. These are built right into your Perl binary, so they
don't take extra time to load. Predefined methods include
isa, can, and
VERSION. All three may be used for both sorts of
invocants: classes and
objects.
The isa method reports whether its invocant
inherits the class name directly or indirectly from the class name
supplied as the argument. This saves having to traverse the hierarchy
yourself, and is much better than testing with an exact check against
the string returned by the ref built-in. You may
even supply a basic type that ref might return as
an argument, such as SCALAR, ARRAY, HASH, or GLOB.
$has_io = $fd->isa("IO::Handle") || $fd->isa("GLOB");
$itza_handle = IO::Socket->isa("IO::Handle");
Type checks like this are sometimes frowned upon as being too
constraining. If you just want to know if a certain method can be
invoked against something, it might be better to just try to invoke
the method you're hoping will be there instead of checking for the
class.
Another possibility is to use another UNIVERSAL method,
can. The can method reports
whether its string argument is a valid method for its invocant. In
fact, it even returns a function reference for that method:
$his_print_method = $obj->can('as_string');
Finally, the VERSION method checks whether the
invocant class has a package global called
$VERSION that's high enough, as in:
Some_Module->VERSION(3.0);
$his_vers = $obj->VERSION( );
However, we don't usually invoke VERSION
ourselves. Remember, in Perl an all-uppercase function name means
that the function will be automatically called by Perl in some way.
In this case, it happens when you say:
use Some_Module 3.0;
If you wanted to add version checking to your Person class explained
earlier, add this to Person.pm:
our $VERSION = "1.01";
Then, in the user code say use
Person 1.01; to make sure that
you have at least that version number or higher available. This is
not the same as loading in that exact version number; it just has to
be at least that high. Lamentably, no mechanism for concurrent
installation of multiple versions of a module yet exists.
13.9.4 See Also
The documentation for the standard UNIVERSAL module; the
use keyword in perlfunc(1)
and in Chapter 11 of Programming Perl
|