Делает ли установка имени писателя для атрибута 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') работает только если я использую автоматически сгенерированное имя доступа, в данном случае "фамилия".

Это предполагаемое поведение или ошибка?

Большое спасибо.

2 ответа

Да потому, что 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',
);

Я думаю, что это намеренное поведение, а не ошибка. Как только вы создадите писателя с writer => 'set_surname' атрибут больше не доступен только для чтения в том смысле, что теперь вы можете изменять его через средство записи. Если вам нужен частный писатель и общедоступный читатель, вы можете поставить подчеркивание перед именем писателя, чтобы указать, что оно является внутренним для класса:

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

Помещение подчеркивания перед именем метода является обычным способом в Perl, чтобы дать подсказку пользователю, что атрибут предназначен только для частного использования.

Другие вопросы по тегам