Bernardo,
On May 16, 2008, at 1:17 PM, Bernardo Rechea wrote:
Stevan Little wrote:
The "after" modifier is applied to accessor generated in the original
class, it is not re-applied for each subclass. When you redefine or
extend the "attr1" attribute in your subclasses you are defining a
completely new "attr1" accessor and therefore overriding the original
one. Remember that "after" is applied to the method specifically, it
does not care if the method was written by you, or by an attribute
and so it will do nothing special if its applied to the accessor.
Thanks for clearing that up, Stevan.
I think I had that expectation because up until now I had done and
seen two
things:
a) if one doesn't change an attribute at all in a subclass (except,
perhaps, to provide a modifier to its accessor), its modifier(s) in
its
superclasses still run.
b) if an attribute whose accessor doesn't have modifiers in the
superclasses is extended, only those properties/options of the
attribute
that are explicitly modified change, and everything else from the
superclass still applies.
So I never had in mind (even though I had read about it) the
implications of
- redefining an attribute in a subclass: everything related to the
attribute (accessor methods, etc.) is generated anew for the
subclass; nor
of
- extending an attribute in a subclass: internally, the attribute
is first
cloned (thereby making it "a completely new 'attr1'") and then the
requested extensions or modifications are applied to the clone (or
it works
_as if_ that were the case?).
In both cases, the accessor code refs are different than the
superclass',
etc. Now, when I both declared a modifier in the superclass _and_
redefined/extended an attribute, the implications had an effect I
didn't
expect...
Anyway, all of the blabber above is just my way of digesting your
answer in
terms of my naive understanding of things.
Nothing naive about it, your exactly correct in your understanding of
things.
Hmm, perhaps it would be a start for a WTF entry?
Sure, patches welcome, or stop by #moose for a commit bit.
Oh, but wait, look at the second case in the code I sent (copied
below).
The 'att1' attribute is redefined with
has 'att1' => (isa => 'Str'),
and yet the 'after' modifiers of both parent and child classes are
triggered (?!).
That is because ..
has 'att1' => (isa => 'Str'),
is not creating an accessor (no "is => 'rw'" or "is => 'ro'")
- Stevan
Bernardo
======================================================================
=======
#!/usr/bin/env perl
{
package Role1;
use Moose::Role;
has 'att1' => ( is => 'rw', isa => 'Any' );
}
{
package Foo;
use Moose;
with 'Role1';
after 'att1' => sub {
my($self, $att1) = @_;
print "In 'after att1' modifier in class Foo\n";
}
}
print "--- Class Foo::Bar redefines att1's 'isa' ---\n";
{
package Foo::Bar;
use Moose;
extends 'Foo';
has 'att2' => ( is => 'rw' );
has 'att1' => ( isa => 'Str');
after 'att1' => sub {
my($self, $att1) = @_;
print "In 'after att1' modifier in class Foo::Bar\n";
}
}
$o = Foo::Bar->new(att1 => 'kk');
$o->att1('dummy');