我正在尝试创建一个对象,该对象将从网络中获取资源,并且需要记住最终找到资源的位置以及我们为其提供的原始 URL。
我不想必须两次指定 URL,也不想每次我想使用 URL 来确定我应该使用“url”属性还是“更新的 URL”时都有大量条件"属性之类的,所以我想我会用 default
创建第二个属性属性设置为从原始 URL 初始化:
package foo;
use Moose;
has 'url' => (
is => 'rw',
isa => 'Str',
required => 1,
);
has 'original_url' => (
is => 'ro',
isa => 'Str',
default => sub { shift->url },
);
如果这行得通(见下文),那么我就可以更改 url
随意,只需使用 url
每当我需要访问“当前”URL 时的属性;稍后,如果我需要查看 url
曾经改变过,我可以比较url
针对 original_url
的属性属性,然后从那里开始。
然而,这样做的问题是这些属性的初始化顺序似乎没有明确定义;有时 default
子original_url
在 url
之前调用属性属性有一个值,这意味着它将返回 undef
,这显然会导致错误。
我想到了 original_url
一个lazy
属性,添加一个 predicate
然后添加 trigger
在 url
更新original_url
如果它的谓词表示它尚未设置,则返回旧值,但结果是触发器被调用 after 值已更改,所以我认为我不能这样做。
有没有一种方法可以完成我正在尝试做的事情而不会导致错误?
最佳答案
无需使用 BUILD
或 BUILDARGS
。
只需使用 init_arg
即可从同一参数初始化两个属性。
#!/usr/bin/perl
use v5.14;
use warnings;
{
package Foo;
use Moose;
has url => (
is => 'rw',
isa => 'Str',
required => 1,
);
has original_url => (
is => 'ro',
init_arg => 'url',
);
}
my $o = Foo->new( url => 'a' );
say $o->url; # a
say $o->original_url; # a
这种方法使得“备份”多个属性变得简单而高效。
for my $name (qw( url ... )) {
has "original_$name" => (
is => 'ro',
init_arg => $name,
);
}
无论您使用哪种技术,您都可能希望避免在原始属性上使用 isa
。验证输入两次没有意义,我怀疑如果这样做会导致消息困惑。
关于perl - Moose - 在第二个属性中保留一个属性的原始值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73035164/