当 (is => “rwp”) 时更改作者前缀

Changing writer prefix when (is => “rwp”)

如果我想更改写保护属性,即

use Moops;

class foo {
  has attr => (is => "rwp");
}

必须使用 _set_attr()

是否可以在不使用显式 writer 的情况下将其更改为 _attr()

尝试了 use MooseX::::AttributeShortcuts -writer_prefix => 'prefix'; 但没有用。

,您需要自己设置 writer.

TLDR:无论如何,底部是一个猴子补丁。


Moops docs 说(强调我的):

Moops uses MooseX::MungeHas in your classes so that the has keyword supports some Moo-specific features, even when you're using Moose or Mouse. Specifically, it supports is => 'rwp', is => 'lazy', builder => 1, clearer => 1, predicate => 1, and trigger => 1.

现在我们来看看Moo。在文档的 has 部分,它说(强调我的):

rwp stands for "read-write protected" and generates a reader like ro, but also sets writer to _set_${attribute_name} for attributes that are designed to be written from inside of the class, but read-only from outside. This feature comes from MooseX::AttributeShortcuts.

好的,继续MooseX::AttributeShortcuts

Specifying is => 'rwp' will cause the following options to be set:

is     => 'ro'
writer => "_set_$name"

然而,这正是它的灵感来源。它实际上是在 Method::Generate::Accessor1.

中的 Moo 中实现的
  } elsif ($is eq 'rwp') {
    $spec->{reader} = $name unless exists $spec->{reader};
    $spec->{writer} = "_set_${name}" unless exists $spec->{writer};
  } elsif ($is ne 'bare') {

更重要的是,这也不是在 Moops 中完成的。事实上,这发生在 Moops 使用的 MooseX::MungeHas 中,但前提是调用者不是 Moo:

            push @code, '  if ($_{is} eq q(rwp)) {';
            push @code, '    $_{is}     = "ro";';
            push @code, '    $_{writer} = "_set_$_" unless exists($_{writer});';
            push @code, '  }';

看起来很清楚。它在生成的代码中。如果仅使用 Moo,下面的解决方案可能会起作用,但我不知道如何强制执行。


您确实可以通过使用 Class::Method::Modifiers 连接到 Moo 的 Method::Generate::Accessor 并在 [=26] 中添加一些逻辑来更改 in Moo =] 修饰符 generate_method。这 对 Moops 不起作用 只要不涉及 Moose-stuff。

use Moops;

BEGIN {
  require Method::Generate::Accessor; # so it's in %INC;
  require Class::Method::Modifiers;
  Class::Method::Modifiers::around( 'Method::Generate::Accessor::generate_method' => sub {
    my $orig = shift;

    #      0      1      2      3      4
    #  my ($self, $into, $name, $spec, $quote_opts) = @_;

    if ($_[3]->{is} eq 'rwp') {
      $_[3]->{writer} = "_explicitly_set_$_[2]" unless exists $_[3]->{reader};
    }

    $orig->(@_);
  });
}

class Foo {
    has attr => ( is => "rwp" );
}

use Data::Printer;

my $foo = Foo->new( attr => 1 );
p $foo;

输出:

Foo  {
    Parents       Moo::Object
    public methods (2) : attr, new
    private methods (1) : _explicitly_set_attr
    internals: {
        attr   1
    }
}

1) 我发现使用 grep.cpan.me.