我试图回答this问题,并认为我可以使用元对象协议为类添加属性。这是一个最小的示例,在此示例中,我尝试在构造后向类test
添加属性Configuration
:
use v6;
class Configuration {
}
my $config = Configuration.new;
my $attr = Attribute.new(
:name('$.test'), # Trying to add a "test" attribute
:type(Str),
:has_accessor(1),
:package(Configuration)
);
$config.^add_attribute( $attr );
$config.^compose();
say "Current attributes: ", join ', ', $config.^attributes();
$attr.set_value( $config, "Hello" ); # <-- This fails with no such attribute '$.test'
say $config.test;
运行此命令时,我得到:
Current attributes: $.test
P6opaque: no such attribute '$.test' on type Configuration in a Configuration when trying to bind a value
in block <unit> at ./p.p6 line 16
答案 0 :(得分:9)
不能在类组合时间之后添加属性,类组合时间是在编译程序时达到结束}
的编译时添加的。 (P6opaque
表示形式就是这种情况。可能存在允许这种表示形式的表示形式并非没有可能,但目前尚未指定。)
此外,在元对象上调用.^add_attribute
,对于class
,属性是按类型而不是按对象的;代码结构表明也许期望是针对每个对象的。没有什么使得不可能具有原型面向对象的(实际上,MOP是经过设计的,因此有人可以在Perl 6中实现这样的对象系统),但是在Perl 6本身中也没有提供任何指定的东西。
因此,对于提供的对象系统,此类操作需要在编译时和关闭}
之前完成。可以通过以下方式实现:
class Configuration {
BEGIN {
my $attr = Attribute.new(
:name('$!test'), # Trying to add a "test" attribute
:type(Str),
:has_accessor(1),
:package(Configuration)
);
Configuration.^add_attribute( $attr );
}
}
my $config = Configuration.new;
say "Current attributes: ", join ', ', $config.^attributes();
$config.^attributes[0].set_value( $config, "Hello" );
say $config.test;
这是Perl 6动态的众多地方之一,主要是通过邀请程序员参与编译时,而不是通过在运行时使所有事情变为可能。
最后,我将注意到有一种方法可以将属性添加到现有对象中,并以每个对象为基础:通过使用does
在其中混合角色。通过沿途更改对象的类型来起作用。 does
here上有一些文档。