Is there a way to assign instance variables declared in a super class, from a constructor in a sub class? I have gotten used to using BUILD() as constructor, but I am wondering if this is a good idea. I.e:
use v6;
class File
{
has $!filename;
}
class XmlFile is File
{
submethod BUILD(:$!filename)
{
}
}
my XmlFile $XF = XmlFile.new(filename => "test.xml");
The code above doesn’t work, prompting an error: "Attribute $!filename not declared in class XmlFile". Is it a matter of using the right accesser? Changing "!" to "." does not solve the problem.
You're halfway there. You have to make the correct two changes to your code:
class File {
has $.filename; # 1. Replace `!` with `.`
}
class XmlFile is File {
submethod BUILD(:$filename) { } # 2. Remove `!`
}
dd my XmlFile $XF = XmlFile.new(filename => "test.xml");
# XmlFile $XF = XmlFile.new(filename => "test.xml")
Replacing $!filename
with $.filename
in the File
class generates a public accessor method (.filename
) in that class.
(Note that attributes are technically always private to a class, i.e. always unavailable to other classes, even trusted ones. When you see the phrase "public attribute" it really means there's a "public accessor" that controls access to a corresponding underlying private attribute.)
Removing the !
twigil from the BUILD
signature in the XmlFile
class means you're no longer trying to reference a non-existent XmlFile
attribute and instead just passing a named argument.
Per Object Construction:
Due to the default behavior of BUILDALL and BUILD submethods, named arguments to the constructor
new
derived fromMu
can correspond directly to public attributes of any of the classes in the method resolution order, or to any named parameter of any BUILD submethod.
(There's that "public attribute" misnomer. It means "attributes with a matching public accessor".)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With