Re: Superclass method modifiers don't run when attribute is extended/modified
[email protected] (Stevan Little)
| Newsgroups | perl.moose |
|---|---|
| Message-ID | <[email protected]> |
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');
>