perl - Moose - 在第二个属性中保留一个属性的原始值

标签 perl moose

我正在尝试创建一个对象,该对象将从网络中获取资源,并且需要记住最终找到资源的位置以及我们为其提供的原始 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 的属性属性,然后从那里开始。

然而,这样做的问题是这些属性的初始化顺序似乎没有明确定义;有时 defaultoriginal_urlurl 之前调用属性属性有一个值,这意味着它将返回 undef ,这显然会导致错误。

我想到了 original_url一个lazy属性,添加一个 predicate然后添加 triggerurl更新original_url如果它的谓词表示它尚未设置,则返回旧值,但结果是触发器被调用 after 值已更改,所以我认为我不能这样做。

有没有一种方法可以完成我正在尝试做的事情而不会导致错误?

最佳答案

无需使用 BUILDBUILDARGS

只需使用 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/

相关文章:

perl - 如何在Perl中制作 “final”方法?

perl - 如何构建所有懒惰的 Moose 功能?

perl - 如何模拟 Moo 角色中定义的方法?

Perl 脚本有效但不能通过 CRON

mysql - 在 perl 中使用 LOAD DATA INFILE 在 MYSQL 中插入值

perl - 我们为什么要使用 Catalyst 的 Context 对象?它的目的是什么?

java - 使用 perl 调用 jar 并使用 STDIN 传递变量

perl - 这样使用 'can'函数是什么意思?

perl - 在 Moose 中,如果一个角色定义了一个具有默认值的属性,我如何在我的消费类中更改该默认值?

perl - 基于 Moose 的 Web 框架