2

编辑:下面添加了答案,问题留在这里仅用于历史目的。

Moose 文档指出:

如果需要,您还可以显式指定用于读取和写入属性值的方法名称。当您希望某个属性可以公开读取但只能私下设置时,这特别方便。例如:

has 'weight' => (
  is     => 'ro',
  writer => '_set_weight',   
 );

如果重量是基于其他方法计算的,这可能很有用。例如,每次调用eat方法时,我们可能会调整权重。这让我们隐藏了权重变化的实现细节,但仍然向类的用户提供权重值。

基于此示例,我编写了以下代码:

has '_current_url' => (
    is => 'ro',
    isa => 'URI',
    writer => '_write_URI_to_current_url',
);

# Thus we ensure only a URI object gets written to current_url always
sub _current_url
{
    my $self = shift;
    $self->_write_URI_to_current_url(URI->new_abs($_[0], $self->start_url));
}

我的目的是确保设置 current_url 始终将其设置为 URI 对象,即使它是使用简单字符串调用的。但是,当我尝试运行代码时,我得到:

无法为 _current_url 的只读访问器赋值

在我试图设置 current_url 的地方(在我的班级内)(使用$self->_current_url($str);)。

这是我和 Moose 在一起的第二天,所以我对这里发生的事情感到很困惑。据我了解,is => 'ro'唯一要求 Moose 不要创建与属性同名的默认写访问器,这种理解是否正确?我怎样才能在这里实现我的目标?

4

2 回答 2

1

好的,我相信我已经找到了问题所在。

我在上面粘贴的_current_url方法被 Moose 生成的同名只读访问器覆盖,因此当我尝试$self->_current_url使用值调用时,它会抛出上述错误以指示只读访问器无法设置值。

我想理想情况下错误消息应该是Cannot assign a value **through** a read-only accessor of _current_url,而不是**to** a read-only accessor

更改子名称以_set_current_url解决问题。我想另一种实现相同目的的方法是告诉 Moose,_current_url is => 'rw'然后创建一个around '_current_url'. 我没有尝试过这种方法。

于 2013-08-30T22:06:38.033 回答
0

比赛迟到了,但刚刚看到这篇文章,不久前又遇到了同样的事情。'_set_current_url' 看起来真的像一个属性访问器而不是一个属性。可能要考虑:

has '_current_url' => {
  is => 'rw',
  isa => 'URI',
  writer => 'set_current_url',
  reader => 'get_current_url'
  }

由于属性是原始的 '_current_url' 并且您有获取/设置属性的访问器,因此这种方式更简洁。

于 2014-01-02T12:39:56.567 回答