Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Re: Class::Std : How does MODIFY_HASH_ATTRIBUTES work?

by xdg (Monsignor)
on Oct 13, 2005 at 21:24 UTC ( [id://500052]=note: print w/replies, xml ) Need Help??


in reply to Class::Std : How does MODIFY_HASH_ATTRIBUTES work?

It's part of the attributes mechanism. It's automatically called to handle the attributes of an appropriate type:

MODIFY_*type*_ATTRIBUTES

This method is called with two fixed arguments, followed by the list of attributes from the relevant declaration. The two fixed arguments are the relevant package name and a reference to the declared subroutine or variable. The expected return value is a list of attributes which were not recognized by this handler. Note that this allows for a derived class to delegate a call to its base class, and then only examine the attributes which the base class didn't already handle for it.

The call to this method is currently made *during* the processing of the declaration. In particular, this means that a subroutine reference will probably be for an undefined subroutine, even if this declaration is actually part of the definition.

You might also want to browse the source of Attribute::Handlers for examples of how they get used.

Updated: expanded answer...

attributes came into being around Perl 5.6. When Perl sees an attribute (see perlsub for the syntax), the attribute gets expanded into a call to the attributes module.

my %name : ATTR; # becomes use attributes (); my %name; attributes::->import(__PACKAGE__, \%name, 'ATTR');

attributes in turn, looks for a MODIFY_*_ATTRIBUTES in the current package or the @ISA array and calls it to handle the attribute. If that function returns any attributes, those are "unhandled" attributes and the import croaks with an error.

MODIFY_*_ATTRIBUTES receives the package name, a reference to the item attributed, and a list of attributes attached. E.g. in Class::Std:

sub MODIFY_HASH_ATTRIBUTES { my ($package, $referent, @attrs) = @_; ...

The rest of that routine checks for an "ATTR" attribute, extracts any information passed along with it, like defaults, and installs the accessors as "usual". For example:

if ($getter = _extract_get($config)) { no strict 'refs'; *{$package.'::get_'.$getter} = sub { return $referent->{ID($_[0])}; } }

The only "magic" here is the way that Perl automatically expands the ":ATTR" into a call to the attributes module. After that, it's just normal function calls between modules.

CAVEAT: this all happens at compile time -- so it's like a BEGIN block and certain things aren't yet set up. This is why in MODIFY_CODE_ATTRIBUTES, the name and reference of the method are just pushed onto a data structure, and the actual handling of the attribute occurs later in the CHECK block, after the method has been compiled.

(This is why anything build with Class::Std won't work with mod_perl, which has no CHECK phase. You can see an approach which will work in my own experimental Object::LocalVars, which requires the module using it to make an explicit function call to give_methods which gets run after its compilation when the module is first loaded in what is effectively a BEGIN phase at that point.)

-xdg

Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://500052]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (5)
As of 2024-03-28 13:29 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found