如何使用元对象协议向对象添加属性?
How to add an attribute to an object using the meta-object protocol?
我试图回答 问题,并认为我可以使用元对象协议将属性添加到 class。这是一个最小的例子,我尝试在构造后将属性 test
添加到 class 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
组合时class后不能添加属性,发生在编译程序时到达收尾}
时的编译时。 (P6opaque
表示就是这种情况。存在允许这样做的表示并非不可能,但此时指定了 none。)
此外,在元对象上调用 .^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.
上有一些文档
我试图回答 test
添加到 class 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
组合时class后不能添加属性,发生在编译程序时到达收尾}
时的编译时。 (P6opaque
表示就是这种情况。存在允许这样做的表示并非不可能,但此时指定了 none。)
此外,在元对象上调用 .^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.