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');


Reply via email to