Perl6:子类中的构造函数

Perl6: Constructors in subclases

有没有办法从子 class 中的构造函数分配在超 class 中声明的实例变量?我已经习惯使用 BUILD() 作为构造函数,但我想知道这是否是个好主意。即:

use v6;      

class File                                                                                                                                                                                                                                    
{                                                                                                                                                                                                                                             
    has $!filename;                                                                                                                                                                                             
}                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       

class XmlFile is File                                                                                                                                                                                                                         
{                                                                                                                                                                                                                                             
    submethod BUILD(:$!filename)                                                                                                                                                                                                              
    {
    }
}

my XmlFile $XF = XmlFile.new(filename => "test.xml");

上面的代码不起作用,提示错误:"Attribute $!filename not declared in class XmlFile"。这是使用正确的访问器的问题吗?改变“!”到 ”。”没有解决问题。

你已经完成了一半。您必须对代码进行 两次 正确更改:

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")

File class 中用 $.filename 替换 $!filename 生成一个 public accessor 方法(.filename) 在那 class.

(请注意,属性 在技术上始终对 class 私有,即始终对其他 class 不可用,甚至 trusted . 当你看到短语 "public attribute" 时,它实际上意味着有一个 "public accessor" 控制着对相应底层私有属性的访问。)

XmlFile class 中的 BUILD 签名中删除 ! twigil 意味着您不再试图引用不存在的 XmlFile 属性,而只是传递一个命名参数。

根据 Object Construction:

Due to the default behavior of BUILDALL and BUILD submethods, named arguments to the constructor new derived from Mu 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.

("public attribute" 用词不当。意思是 "attributes with a matching public accessor"。)

如果您希望它保持私密,您也可以随时将其直接添加到子class。 (也许你不控制你正在 subclassing 的 class?)当然,你必须注意你的 class 和 sub[ 之间哪些方法做了哪些事情=23=]。

class File                                                                                                                                                                                                                                    
{                                                                                                                                                                                                                                             
    has $!filename;                                                                                                                                                                                             
}                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       

class XmlFile is File                                                                                                                                                                                                                         
{   
    has $!filename;

    submethod BUILD(:$!filename)                                                                                                                                                                                                              
    {
    }
}

my XmlFile $XF = XmlFile.new(filename => "test.xml");

您可能还想考虑使用 'has a' 关系而不是 'is a' 关系,方法是根据您的需求,使 class XmlFile 的属性包含 class File正在努力做。

handles 特性使委托给另一个 class 成为直接子class 的一个特别简单和有用的选择。

class XmlFile
{
    has File $!file handles<some methods>;
    ...
}