【问题标题】:Does setting a writer name for a Moo read-only attribute make it read-write?为 Moo 只读属性设置写入器名称是否使其可读写?
【发布时间】:2018-05-05 08:54:09
【问题描述】:

我正在研究 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') 仅在我使用自动生成的访问器名称时才有效,在本例中为“姓氏”。

这是预期的行为还是错误?

非常感谢。

【问题讨论】:

    标签: perl attributes moo


    【解决方案1】:

    是的,因为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',
    );
    

    【讨论】:

      【解决方案2】:

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

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

      在方法名前加下划线是 Perl 中常用的方法,它可以提示用户某个属性仅供私人使用。

      【讨论】:

      • 谢谢你,你说得对。我在 Moose 'has is' 选项中找到了这个解释:“如果您需要更多地控制访问器的命名方式,您可以使用从 Class::MOP::Attribute 继承的读取器、写入器和访问器选项,但是如果您使用这些,您将不需要 is 选项”。所以 Moo 似乎也以同样的方式工作。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-03-05
      • 2014-10-20
      • 1970-01-01
      • 1970-01-01
      • 2010-12-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多