Perl 为Moo只读属性设置写入程序名称是否使其成为读写?

Perl 为Moo只读属性设置写入程序名称是否使其成为读写?,perl,attributes,moo,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',

我在研究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
当我使用accessor时,也会发生同样的行为。 (is=>'ro')仅在我使用自动生成的访问器名称时有效,在本例中为“姓氏”

这是一个预期的行为还是一个bug


非常感谢。

我认为这是故意的行为,而不是错误。只要您使用
writer=>'set\u names'
创建一个writer,该属性就不再是只读的,您现在可以通过writer对其进行修改。如果您想要一个私有编写器和一个公共读取器,您可以在编写器的名称前面加一个下划线,以指示它是类的内部编写器:

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

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

是的,因为
is
不会使任何内容成为只读;它只是创建一个访问器

  • is=>'rw'
    只是
    accessor=>'attribute\u name'
    的快捷方式
  • is=>'ro'
    只是
    reader=>'attribute\u name'
    的快捷方式
如果指定一个
编写器
,则即使使用了
is=>“ro”
,也可以写入属性

如果我想要一个公共阅读器和一个私有/受保护的编写器,我使用

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


谢谢,你完全正确。我在Moose的“has is”选项中找到了这样的解释:“如果您需要更多地控制访问器的命名方式,您可以使用从Class::MOP::Attribute继承的reader、writer和accessor选项,但是如果您使用这些选项,您将不需要is选项”。所以Moo似乎也是这样。
has surname => (
    reader => 'surname',
    writer => '_set_surname',
);