Reputation: 531
Is it possible to override an attribute of a role to provide a default?
role A {
has $.a;
}
class B does A {
has $.a = "default";
}
my $b = B.new;
This results in a compile error:
===SORRY!=== Error while compiling:
Attribute '$!a' already exists in the class 'B', but a role also wishes to compose it
Upvotes: 6
Views: 111
Reputation:
Since methods in R
may refer to $!a
there would be ambiguity what attribute is referred to.
Use the submethod BUILD to initialise inherited/mixedin attributes.
role R { has $.a };
class C does R {
submethod BUILD { $!a = "default" }
};
my $c = C.new;
dd $c;
# OUTPUT«C $c = C.new(a => "default")»
Depending on your usecase you may be better of to set the default via a role parameter.
role R[$d] { has $.a = $d };
class C does R["default"] { };
my $c = C.new;
dd $c;
# OUTPUT«C $c = C.new(a => "default")»
Upvotes: 5
Reputation: 169523
No, it's not possible to redeclare an attribute - but you can initialize it using the BUILD
submethod of the class:
role A {
has $.a;
}
class B does A {
submethod BUILD(:$!a = 'default') {}
}
Note that if you just set the value within the body of BUILD
instead of its signature via
class B does A {
submethod BUILD { $!a = 'default' }
}
the user would not be able to overwrite the default by providing a named initializer via B.new(a => 42)
.
Another, more elegant approach that is especially useful if setting the default is something you expect to do a lot (ie the default value can be regarded as part of the role's interface) is making it a parameter:
role A[$d] {
has $.a = $d;
}
class B does A['default'] {}
Upvotes: 2