8.2. Attribute::Handlers
Implements a simpler definition of
attribute handlers. When inherited by a package, Attribute::Handlers
allows that package's class to define handler
subroutines for specific attributes. When inherited by a package,
these handlers will be called by the same names as the original
attribute-handling subroutines. Attribute handlers will be called at
one of the following compilation phases: BEGIN, CHECK, INIT, or END
blocks. Note that Attribute::Handlers is shipped with the Perl source
kit as of Version 5.8.
Handlers are
defined as subroutines and named as the desired attribute. In the
following example, the attribute is :ATTR, which
lives in a subroutine that's called
Nate1() in the HandlerBing class:
package HandlerBing;
use Attribute::Handlers;
sub Nate1 :ATTR {
my(@attrs) = @_; # We simply want to test by dumping the attributes
print "attributes: \n",
join("\n", @attrs), "\n";
}
# true.
1;
This stub for the HandlerBing class creates a handler for the
attribute :Nate1. When you want to use this
handler while within HandlerBing, you can do the following:
sub Nate2 :Nate1 {
my (@stuff) = @_;
print STDERR "in Nate2 ", join("\n", @stuff), "\n";
}
When you call Nate2, it invokes the
Nate1 handler and passes the following elements
into the @_ array:
- 0
-
The name of the package in which the handler was declared
- 1
-
A reference to the symbol table entry (a typeglob) that contains the
subroutine
- 2
-
A reference to the subroutine
- 3
-
The name of the attribute itself
- 4
-
Any data associated with that attribute
- 5
-
The name of the compilation phase in which the handler was invoked
The same holds true for declaring any variables with the
:Nate1 attribute within HandlerBing:
my $monica :Nate1;
my $phoebe :Nate1;
Attribute::Handlers also supports typed lexicals. This is a nice
feature, since you can invoke a handler from a package that defines
another one from whatever package you're in (or
writing!). For example:
package MustNotSeeTV;
my HandlerBring $whatever : Nate1;
# true
1;
You can apply handlers only by type, if you wish. You can do this by
passing a built-in type to :ATTR:
package ReRun;
sub Tiresome :ATTR(HASH) { print "your reruns have become tiresome\n"; }
# true
1;
In the above code, Tiresome is an attribute
handler that applies only to HASH es. And
certainly, you can declare separate handlers (of the same names) for
the other types.
If you have problems passing certain data to a handler, such as
now..later or laugh@you, you
can use the RAWDATA type to pass this data
cleanly:
sub RawLikeSushi : ATTR(RAWDATA) { ... do something ... }
Attribute::Handlers
implements the following diagnostics (from the Attribute::Handlers
manpage):
- Bad attribute type: ATTR(%s)
-
An attribute handler was specified with an
:ATTR(ref_type),
but the type of referent it was defined to handle
wasn't one of the five permitted:
SCALAR, ARRAY,
HASH, CODE, or
ANY.
- Attribute handler %s doesn't handle %s attributes
-
A handler for attributes of the specified name was defined, but not
for the specified type of declaration. Typically encountered when
trying to apply a VAR attribute handler to a
subroutine, or a SCALAR attribute handler to
another type of variable.
- Declaration of %s attribute in %s package may clash with future reserved word
-
A handler for an attribute with an all-lowercase name was declared.
An attribute with an all-lowercase name might mean something to Perl
itself someday, even though most don't yet. Use a
mixed-case attribute name instead.
- Can't have two ATTR specifiers on one subroutine
-
You just can't, okay? Instead, put all the
specifications together, separated by commas in a single
ATTR(specifications).
- Can't autotie a %s
-
You can declare autoties only for types SCALAR,
ARRAY, and HASH.
They're the only things (apart from typeglobs, which
are not declarable) that Perl can tie.
- Internal error: %s symbol went missing
-
Something is rotten in the state of the program. An attributed
subroutine ceased to exist between the point where it was declared
and the point where its attribute handler(s) would have been called.
- Won't be able to apply an END handler
-
You tried to define an END handler for an
attribute that is applied to a lexical variable. Since the variable
may not be available during END, this will
fail.
 |  |  | | 8. Standard Modules |  | 8.3. attributes |
Copyright © 2002 O'Reilly & Associates. All rights reserved.
|