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. Hmm, perhaps it would be a start
for a WTF entry?


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 (?!).


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