为Moo只读属性设置编写器名称是否可以读写?

时间:2018-05-05 08:54:10

标签: perl attributes moo

我正在研究Moo并且碰到了这个基本问题。 如果我为只读属性设置访问者或编写者名称,则该属性变为可写。访问者或作者是否暗示该属性是可写的,即使它被设置为只读(is =>'ro')?

这是类代码:

#!/home/fl/perl5/perlbrew/perls/perl-5.26.1/bin/perl
package MooPerson;
use Moo;
use namespace::clean;

has firstname => (
    is     => 'rw',
    reader => 'get_firstname',
    writer => 'set_firstname',
);

has surname => (
    is      => 'ro',
    reader  => 'get_surname',
    writer  => 'set_surname',
);

sub get_fullname {
    my ($self) = @_;
    my $firstname = $self->get_firstname;
    my $surname   = $self->get_surname;
    return "$firstname $surname";
}
1;

目标代码:

#!/home/fl/perl5/perlbrew/perls/perl-5.26.1/bin/perl
use lib 'lib';
use MooPerson;
use feature 'say';
use strict;
use warnings;

say "new object person";
my $person = MooPerson->new(
    firstname => 'Homer',
    surname   => 'Simpson',
);

say "person->get_firstname: " . $person->get_firstname();
say "person->get_surname: " . $person->get_surname();

say "\nchange firstname and surname";
$person->set_firstname('Aristotle');
$person->set_surname('Amadopolis');

say "person->get_firstname: " . $person->get_firstname();
say "person->get_surname: " . $person->get_surname();

结果:

fl@dancertest:~/perltest$ ./firstMoo.pl
new object person
person->get_firstname: Homer
person->get_surname: Simpson

change firstname and surname
person->get_firstname: Aristotle
person->get_surname: Amadopolis

使用访问器时会出现相同的行为。 (is =>'ro')仅在我使用自动生成的访问者名称时才有效,在本例中为“surname”。

是预期的行为还是错误?

非常感谢。

2 个答案:

答案 0 :(得分:3)

是的,因为is没有任何只读内容;它只是创建一个访问者。

  • is => 'rw'只是accessor => 'attribute_name'
  • 的快捷方式
  • is => 'ro'只是reader => 'attribute_name'
  • 的快捷方式

如果您指定writer,即使您使用了is => 'ro',也可以写入该属性。

如果我想要一个公共读者和私人/受保护的作家,我会使用

has surname => (
    reader => 'get_surname',
    writer => '_set_surname',
);

has surname => (
    reader => 'surname',
    writer => '_set_surname',
);

答案 1 :(得分:2)

我认为这是预期的行为而不是错误。只要您使用writer => 'set_surname'创建一个编写器,该属性就不再是只读的,因为您现在可以通过编写器对其进行修改。如果你想要一个私人作家和一个公共读者,你可以在作者姓名前加上一个下划线,表明它是该类的内部:

has surname => (
    is      => 'ro',
    reader  => 'get_surname',
    writer  => '_set_surname',
);

在方法名称前面加下划线是Perl向用户提示某个属性仅供私人使用的常用方法。

相关问题