我尝试创建属性特征。用例是将类的某些属性标记为" crudable"在对象到文档映射的上下文中,而其他则不是。
role crud {
has Bool $.crud is default(True);
}
multi trait_mod:<is>(Attribute $a, crud, $arg) {
$a.container.VAR does crud($arg);
}
class Foo {
has $.bar is rw;
# Provide an extra nested information
has $.baz is rw is crud(True);
}
通过阅读和改编some example code,我设法得到了一些似乎可以做我想要的东西。这是a snippet with test case。
当我实例化一个新的Foo
对象并设置$.bar
属性(is
而非crud
)时,它看起来像是:
.Foo @0
├ $.bar is rw = 123456789
└ $.baz is rw = .Scalar+{crud} @1
└ $.crud +{crud} = True
我从中理解的是$.baz
属性得到了我称之为元属性的独立于其潜在价值的东西。
对我来说这很好看(如果我理解我在这里做了什么,我的特质使用不是一个肮脏的黑客)。有可能达到$foo.baz.crud
True
。虽然,我不太了解.Scalar+{crud}
的含义,以及我是否可以在那里设置一些内容以及如何设置。
当我尝试设置$.baz
实例属性时,会返回此错误:
Cannot modify an immutable Scalar+{crud} (Scalar+{crud}.new(crud => Bool::True))
in block <unit> at t/08-attribute-trait.t line 30
注意:这是我设法获得的工作解决方案最接近的事情。对于实例化的Foo类的不同实例,我不需要不同的crud设置。
我从不想改变布尔值,实际上,一旦对象被实例化,只是将它提供给具有is crud
的属性。我甚至不想将True
或False
值作为参数传递:如果默认情况下可以将布尔特征属性设置为True
,那就足够了。我没有设法做到这一点,比如:
multi trait_mod:<is>(Attribute $a, :$crud!) {
# Something like this
$a.container.VAR does set-crud;
}
class Foo {
has $.bar is rw;
has $.baz is rw is crud;
}
我想做一些不可能的事吗?我如何调整此代码以实现此用例?
答案 0 :(得分:4)
这里有几件事情。首先,trait_mod
的签名看起来是错误的。其次,当特征的名称与现有角色相同时,似乎存在不良交互。我相信这应该是一个NYI异常,但显然它在解析时出错,或者在尝试生成错误消息时出错。
无论如何,我认为这就是你想要的:
role CRUD {}; # since CRUD is used as an acronym, I chose to use uppercase here
multi trait_mod:<is>(Attribute:D $a, :$crud!) { # note required named attribute!
$a.^mixin: CRUD if $crud; # mixin the CRUD role if a True value was given
}
class A {
has $.a is crud(False); # too bad "is !crud" is invalid syntax
has $.b is crud;
}
say "$_.name(): { $_ ~~ CRUD }" for A.^attributes; # $!a: False, $!b: True
希望这有帮助。