我想为一个属性编写一个特征,为它提供一个代理,这样我就可以操纵 sees 背后的值,甚至可以为$!direct-access
在一个班级内。
这就是我现在所拥有的,但正如您所看到的,实际的 get/set 或 store/fetch 方法从未被调用。我可能没有正确应用它们,但我发现的唯一示例看起来有大量额外的代码,它们的作用超出了我的需要,但我无法隔离重要的部分。
# The below shows on a Str more or less how I'd expect things to work
# although the %data wouldn't be hard coded of course
my Str $localized := do {
my %data = hi => "hola", bye => "adiós";
my $str = "";
Proxy.new:
:STORE{ $str = @_[1] },
:FETCH{ with %data{$str} { $_ } else { $str } }
}
$localized = "hi";
say $localized;
$localized = "bye";
say $localized;
$localized = "not defined";
say $localized;
# This seems to almost work,
multi trait_mod:<is>(Attribute:D $a, :$localized!) {
say $a.container.VAR.WHAT;
$a.container.VAR does role Localized {
has $!str;
method STORE($a) { say "store!"; $!str = $a }
method FETCH {say "fetch!"}
}
}
class Foo {
has Str $.text is localized;
}
my $foo = Foo.new;
say $foo.text, " <-- should be in Spanish";
$foo.text = "bye";
say $foo.text, " <-- should be in Spanish";
虽然在这种情况下STORE
方法被正确调用,但 fetch 方法未正确调用,其要点$foo.text
is Scalar+{Localized}.new
,这表明我没有完全正确地应用事物。
您需要安排Proxy
to be bound到属性中,这样就有一个Proxy
那里而不是一个Scalar
通常由类初始化逻辑创建的容器。这可以通过设置构建逻辑来实现(尽管如果采用这种方法,您将覆盖任何初始默认值),并使用它将属性绑定到新的Proxy
在每个对象创建时:
multi trait_mod:<is>(Attribute:D $a, :$localized!) {
$a.set_build: -> \SELF, | {
$a.set_value: SELF, Proxy.new:
STORE => -> $, $val { say "store $val" },
FETCH => { say "fetch!"; 42 }
}
}
然后这将调用FETCH
and STORE
回调(注意FETCH
可能会因内部原因而被调用,例如类型检查以及您直接看到的访问):
class C {
has $.attr is localized is rw;
}
my $c = C.new;
$c.attr = 'foo';
my $x = $c.attr;
此示例演示了它也可以在类内部的属性读取上起作用:
class C {
has $.attr is localized is rw;
method m() {
$!attr = 'foo';
my $x = $!attr
}
}
C.new.m;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)