home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


13.8. Determining Subclass Membership

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 can be called on an arbitrary object.

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

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.

In version 5.003, no methods were predefined in UNIVERSAL, but you could put whatever you felt like into it. However, as of version 5.004, UNIVERSAL has a few methods in it already. These are built right into your Perl binary, so they don't take extra time to load. Predefined methods include isa , can , and VERSION . The isa method tells you whether an object or class "is" another one, without having to traverse the hierarchy yourself:

$has_io = $fd->isa("IO::Handle");
$itza_handle = IO::Socket->isa("IO::Handle");

Arguably, it's usually best to try the method call. Explicit type checks like this are sometimes frowned upon as being too constraining.

The can method, called on behalf of that object or class, reports back whether its string argument is a callable method name in that class. In fact, it gives you back a function reference to that method:

$his_print_method = $obj->can('as_string');

Finally, the VERSION method checks whether the class (or the object's 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 call 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 above, add this to Person.pm:

use vars qw($VERSION);
$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 support currently exists for concurrent installation of multiple versions of a module.

See Also

The documentation for the standard UNIVERSAL module; the use keyword in perlfunc (1) and in Chapter 3 of Programming Perl