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: ", join(" ", @attrs), " "; } # 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(" ", @stuff), " "; }
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 "; } # 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):
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
.
%s
doesn’t handle %s
attributesA 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.
%s
attribute in %s
package may
clash with future reserved wordA 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.
ATTR
specifiers on one subroutineYou just can’t, okay? Instead, put all the specifications
together, separated by commas in a single ATTR(
specifications
)
.
%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.
%s
symbol
went missingSomething 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.
END
handlerYou 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.
3.149.242.175