Subject: | Inconsistent behavior when mixing default and builder when extending a class |
As described in the attached file, when extending a Parent class, and overriding the attribute definition we could end up using the parent or kid builder depending if the parent class is using builder or default for the attribute
In the two attached scripts (which are very similar, only the definition of 'name' differs in the parent class)
Show quoted text
> prove -v buider_from_kid.pl # succeeds
whereas
Show quoted text> prove -v builder_from_parent.pl # fails as the builder is going to be ignored in the kid...
We could expect that both behave the same way, as builder seems to be an alternate of providing default.
I do not think we could call it a feature.
Suggested resolution when override attribute provides default or builder, clear the other on the parent class?
Subject: | builder_from_kid.pl |
package Parent;
use Moo;
# when Parent is using default and Kid is using builder, we use _build_name from Parent
#has 'name' => ( is => 'rw', lazy => 1, default => \&_build_name );
# when Parent is using builder and Kid is using builder, we use _build_name from Kid
has 'name' => ( is => 'rw', lazy => 1, builder => 1 );
sub _build_name { 'your father' }
package Kid;
use Moo;
extends 'Parent';
has '+name' => ( is => 'rw', lazy => 1, builder => 1 );
sub _build_name { 'Son' }
package Main;
use Test::More;
my $kid = Kid->new;
is $kid->name, 'Son', "using the builder defined by the Kid class";
Subject: | builder_from_parent.pl |
package Parent;
use Moo;
# when Parent is using default and Kid is using builder, we use _build_name from Parent
has 'name' => ( is => 'rw', lazy => 1, default => \&_build_name );
# when Parent is using builder and Kid is using builder, we use _build_name from Kid
#has 'name' => ( is => 'rw', lazy => 1, builder => 1 );
sub _build_name { 'your father' }
package Kid;
use Moo;
extends 'Parent';
has '+name' => ( is => 'rw', lazy => 1, builder => 1 );
sub _build_name { 'Son' }
package Main;
use Test::More;
my $kid = Kid->new;
is $kid->name, 'Son', "using the builder defined by the Kid class";