有没有办法从子类的构造函数中分配超类中声明的实例变量?我已经习惯使用BUILD()作为构造函数,但我想知道这是不是一个好主意。即:
use v6;
class File
{
has $!filename;
}
class XmlFile is File
{
submethod BUILD(:$!filename)
{
}
}
my XmlFile $XF = XmlFile.new(filename => "test.xml");
上面的代码不起作用,提示错误:"属性$!filename未在类XmlFile"中声明。这是使用正确的访问者的问题吗?改变"!"到"。"没有解决问题。
答案 0 :(得分:4)
你已经到了一半。您必须对代码进行正确的两次更改:
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")
在$!filename
类中使用$.filename
替换File
会在该类中生成公共访问者方法(.filename
)。
(请注意,属性在技术上总是对一个类是私有的,即对其他类总是不可用,甚至是trusted个。当你看到短语“public attribute”时,它真的意味着有一个“公共访问器”,用于控制对相应底层私有属性的访问。)
从!
类中的BUILD
签名中删除XmlFile
twigil意味着您不再尝试引用不存在的XmlFile
属性,而只是通过命名参数。
由于BUILDALL和BUILD子方法的默认行为,从
new
派生的构造函数Mu
的命名参数可以直接对应于方法解析顺序中任何类的公共属性,或者任何BUILD子方法的任何命名参数。
(“公共属性”用词不当。它表示“具有匹配公共访问者的属性”。)
答案 1 :(得分:0)
如果您希望它保持私有,您也可以将其直接添加到子类中。 (也许你不能控制你正在继承的类?)当然,你必须要小心你的类和子类之间的哪些方法。
class File
{
has $!filename;
}
class XmlFile is File
{
has $!filename;
submethod BUILD(:$!filename)
{
}
}
my XmlFile $XF = XmlFile.new(filename => "test.xml");
你可能还想考虑使用'有一个'关系而不是'是一个'通过使class XmlFile
属性保持class File
取决于您要执行的操作来建立关系。
handles特征使得委托给另一个类成为直接子类化的一个特别简单有用的选项。
class XmlFile
{
has File $!file handles<some methods>;
...
}