如何使用元对象协议向对象添加属性? [英] How to add an attribute to an object using the meta-object protocol?

查看:85
本文介绍了如何使用元对象协议向对象添加属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图回答这个问题,并认为我可以使用元对象协议将属性添加到类。这是一个最小的示例,在该示例中,我尝试在构造后将属性 test 添加到类 Configuration 中:

I was trying to answer this question, and thought I could use the meta-object protocol to add attributes to a class. Here is a minimal example where I try to add an attribute test to the class Configuration after construction:

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;

运行此命令时,我得到:

When I run this, I get:

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


推荐答案

属性不能为在类组合时间之后添加,该时间发生在编译时,即在编译程序时达到结束} 时。 ( P6opaque 表示形式就是这种情况。存在可以允许这种表示形式的表示形式并非不可能,但此时未指定。)

Attributes cannot be added after class composition time, which occurs at compile time when the closing } is reached when compiling the program. (This is the case for the P6opaque representation. It's not impossible that a representation could exist that allows this, but there's none specified at this time.)

此外,在元对象上调用。^ add_attribute ,对于属性是按类型而不是按对象的;代码结构表明,期望可能是针对每个对象的。没有什么使得不可能具有原型面向对象的(实际上,MOP是经过设计的,因此有人可以在Perl 6中实现这样的对象系统),但是在Perl 6本身中也没有指定提供这种对象的东西。

Further to that, .^add_attribute is called on the meta-object, and for a class the attributes are per type, not per object; the code structure suggests that perhaps the expectation was per object. There's nothing that makes it impossible to have prototype object orientation (actually the MOP is designed so somebody could implement such an object system in Perl 6), but again there's nothing specified in Perl 6 itself that provides this.

因此,对于提供的对象系统,这种操作需要在编译时以及关闭} 之前完成。可以通过以下方式实现:

Thus with the provided object system, such manipulation needs to be done at compile time, and before the closing }. That can be achieved as follows:

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动态的地方之一,主要是通过邀请程序员参与编译来实现的

This is one of the many places where Perl 6 is dynamic primarily by inviting the programmer to participate in compile time, rather than by making all things possible at runtime.

最后,我要指出的是,有一种方法可以将属性添加到现有对象,并在每个对象上添加属性。 -基于对象:通过使用 does 来混合角色。通过在此过程中更改对象的类型来起作用。在 此处

Finally, I'll note that there is a means to add attributes to an existing object, and on a per-object basis: by using does to mix a role in to it. That works by changing the type of the object along the way. There's some documentation on does here.

这篇关于如何使用元对象协议向对象添加属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆