【问题标题】:How to add a class attribute dynamically?如何动态添加类属性?
【发布时间】:2019-09-18 12:47:37
【问题描述】:

如何动态地将属性添加到类中?我试过了,但它抱怨缺少方法,我不知道为什么,因为我没有尝试添加方法。

use v6.d;

class Foo does Metamodel::AttributeContainer {
    submethod BUILD(:$attr) {
        my $a = Attribute.new(:name($attr), :type(Str), :package(Foo));
        self.add_attribute(self, $a);
    }
}

my Foo $foo = Foo.new(:attr('bar'));
$foo.bar = 'baz';  # No such method 'bar' for invocant of type 'Foo'
say $foo.bar;

【问题讨论】:

标签: metaprogramming raku


【解决方案1】:

一旦一个类被组合,就没有办法向它添加一个属性——也就是说,在它的结束卷曲 } 被解析之后。一般来说,使用元模型完成的声明性事情需要在编译时完成。

关于您在问题中编写的代码:

  • 从概念上讲,属性存在于每个类中,而不是每个对象,因此无法实现这样的工作。
  • 即使把它放在一边,扮演Metamodel::AttributeContainer 角色在这里也无济于事;它将被组合成一个元类,其中包含有关属性的元数据,而不是具有被声明的属性的类。
  • 没有找到方法bar的错误是因为属性访问器——即使是生成的——只是一个普通的方法。

如果不知道您首先要解决的问题,就很难知道该建议什么。不管是什么,都无法通过尝试为每个对象添加属性来解决。或许可以考虑:

  • 使用 mixin,这是一种更改单个对象的方法
  • 拥有一个包含哈希的类来存储其数据,然后使用FALLBACK 方法将方法调用解析为有效键的哈希访问

【讨论】:

  • 正如您所建议的,FALLBACK 正是我已经在做的事情,以获得对事物的读取权限。我有一个哈希值,我根据键从中获取值。我正在寻找 FALLBACK 的写入版本,它允许我根据键更新哈希中的值。
  • is raw 添加到FALLBACK 方法中,它将返回左值,因此可以将其分配给。
  • 我搞定了。谢谢你。我在保护条款上挂了一段时间.. 只是普通的旧 %!attrs{$name};return %!attrs{$name} if %!attrs{$name}; 因只读错误而失败的地方工作。我重新安排了事情以使用正确的 if/else 并且它起作用了。
  • 由于子方法只添加了一个自定义属性,你可以简单地存储$!custom_attribute$!custom_attribute_name
  • @gdonald 你也可以使用return-rw
猜你喜欢
  • 1970-01-01
  • 2017-01-13
  • 2011-01-15
  • 2019-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多