Here is an edited version based on your comment. This way the default for the child class is set in the child class, but may be explicitly set if needed.
use v6.d;
class Foo {
has $.name = 'John'
}
class Bar is Foo {
method new( *%h ) {
%h<name> //= 'Jane';
nextwith( |%h )
}
}
Foo.new.say; # OUTPUT: Foo.new(name => "John")
Bar.new.say; # OUTPUT: Bar.new(name => "Jane")
Bar.new(name => 'Dora').say; # OUTPUT: Bar.new(name => "Dora")
Since my previous version relied on TWEAK, I thought it would be fun to try that way too.
class Foo {
has $!name;
multi method name { #getter
$!name
}
multi method name( $value ) { #setter
$!name = $value
}
submethod TWEAK {
$!name //= 'John'
}
method gist(::T:) { #captures type of its invocant
"{::T.^name}.new(name => \"$!name\")"
}
}
class Bar is Foo {
submethod TWEAK( :$name ) {
self.name: $name // 'Jane'
}
}
Foo.new.say; # OUTPUT: Foo.new(name => "John")
Bar.new.say; # OUTPUT: Bar.new(name => "Jane")
Bar.new(name => 'Dora').say; # OUTPUT: Bar.new(name => "Dora")
This is a bit trickier since the public attribute shorthand has $.name; auto-generates (i) public accessor getter/setter methods with (ii) a proxy for easy assignment and (iii) adjusts the .gist for a quick and easy view of all public attrs via .say. BUT these features are not ready until construction is done.
Therefore this example has to have explicit setter/getter multi methods with has $!name; as private attribute.
The public attribute shorthand is like training wheels for OO that provides easy use of basic OO as transparent data structures with a low learning curve (like in Python). Sidestepping this is like putting raku into more formal OO mode with proper encapsulation. As you climb the OO hill, with inheritance, roles, delegation, trust and so on, raku gently encourages you to get more formal.
Here we need to do this to get a way to access the $!name attribute in the parent class during construction.
It's easy enough now for Foo's TWEAK submethod to apply the default by assigning to it's private $!name.
Now Bar's TWEAK submethod can use the getter/setter since all regular methods are available at TWEAK time. (Actually you get the same outcome if you use BUILD instead of TWEAK in this example.)
A couple of other adjustments -
- say calls
.gist on an object - so we need to explicitly put private attributes back in with a custom .gist if you want to show them
- here I use a
::T type capture so that I only have to do that once and the same parent method works for all child classes
- need to use
self. instead of $. at TWEAK time (all that $. virtual method machinery comes in afterwards), and
- need to use the method syntax for setter methods
self.name: 'value' (which IMO is a nicer way to go self.name('value')) since the public attr proxy is not there
The following is a bit out of context now after this edit, but I will leave here anyway.
The magic is that special methods new, BUILD and TWEAK will auto set named attrs based on their signature alone.
Here's why I prefer to use TWEAK instead of BUILD:
BUILD may set an attribute, but it does not have access to the
contents of the attribute declared as its default as they are only
applied later. TWEAK on the other hand is called after default values
have been applied and will thus find the attributes initialized. So it
can be used to check things or modify attributes after object
construction.