【问题标题】:How can I acces read-only attributes of Moose objects?如何访问 Moose 对象的只读属性?
【发布时间】:2010-10-01 13:39:01
【问题描述】:

我是Moose 的绝对新手,到目前为止,我已经阅读了Moose 和大部分Cookbook

有几件事我不明白。我创建了以下包:

package MyRange;

use Moose;
use namespace::autoclean;

has [ 'start', 'end' ] => (
    is       => 'ro',
    isa      => 'Int',
    required => 1,
);

__PACKAGE__->meta->make_immutable;

1;

然后:

use MyRange;    
my $br = MyRange->new(
    start                => 100,
    end                  => 180
);

现在我可以使用例如访问我的字段$br->{start},但我也可以使用例如修改它们(尽管它们是“只读的”) $br->{start}=5000。我还可以添加新的密钥,例如$br->{xxx}=111

我错过了什么吗?对象不是以某种方式受到保护吗? ro是什么意思?

【问题讨论】:

    标签: perl moose


    【解决方案1】:

    当您说is => 'ro' 时,您告诉 Moose 为您创建只读访问器,即读取器方法。你称之为

    $br->start;
    

    $br->end;
    

    使用这些方法设置属性会导致异常:

    $br->start(42);
    

    如果您使用了is => 'rw',那么上面的方法将起作用并更新属性的值。

    您所做的是对对象的直接哈希访问,这违反了封装,并且在使用 Moose 时不应该是必需的。

    Moose 手册,即Moose::Manual 命名空间下的所有文档都详细解释了这一点。此类问题的一个很好的起点可能是Moose::Manual::Attributes

    【讨论】:

    • +1 谢谢!如果可以的话,跟进:我有一些不需要的字段。如果未设置它们,并且我尝试访问那些 undef 值,我想得到一个错误。我应该为他们每个人设置一个阅读器吗?或者也许在default中使用一些die-like sub?
    • 您可能想创建一个新问题以获得更详细的答案,但是:您是否有一个最初不需要值的设计,但允许用户稍后使用 writer 填写它们方法并且必须在调用某些使用它的功能之前这样做?大多数时候,您可能应该在那里重新考虑您的设计,但在极少数情况下,我的MooseX::LazyRequire 扩展可能会有所帮助。所做的只是使属性成为必需,但将异常从构造时间推迟到访问 attr 的时间。
    • 另外请注意,您可以要求 Moose 为您生成 predicate 方法。您可以使用它们来显式检查是否已通过构造函数或编写器方法为某些属性设置了值。这对于不需要且undef 是有效值的属性特别方便。
    【解决方案2】:

    当您使用$br->{start} 访问该属性时,您将绕过访问器并直接访问底层 Moose 实现。你可以这样做,但你不应该这样做。此外,如果 Moose 更改了实现,您的代码将会中断。

    您应该改为使用访问器方法访问属性:

    my $start = $br->start;
    

    当你说属性是'RO'时,意味着你不能使用访问器改变属性值:

    $br->start(32);
    

    【讨论】:

      猜你喜欢
      • 2011-07-04
      • 2018-09-10
      • 1970-01-01
      • 2015-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多