代码之家  ›  专栏  ›  技术社区  ›  Håkon Hægland

如何使用元对象协议向对象添加属性?

  •  9
  • Håkon Hægland  · 技术社区  · 6 年前

    我想回答 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
    
    1 回复  |  直到 5 年前
        1
  •  9
  •   Jonathan Worthington    6 年前

    不能在类组合时间之后添加属性,该时间发生在关闭时的编译时 } 在编译程序时到达。(事实上 P6opaque

    除此之外, .^add_attribute 在元对象上调用,对于 class

    因此,对于所提供的对象系统,这种操作需要在编译时和关闭之前完成 } . 可以实现如下目标:

    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;
    

    最后,我将注意到有一种方法可以向现有对象添加属性,并且基于每个对象:通过使用 does 把一个角色融入其中。这是通过改变对象的类型来实现的。有一些关于 here

    推荐文章