0

書き込み保護属性を変更したい場合。

use Moops;

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

使用する必要があります_set_attr()

_attr()explicit を使用せずにそれを変更することは可能writerですか?

試してみuse MooseX::::AttributeShortcuts -writer_prefix => 'prefix';ましたが、うまくいきませんでした。

4

1 に答える 1

4

いいえ、 を設定して自分で行う必要がありますwriter

TLDR: 一番下には、とにかくそれを行うためのモンキー パッチがあります。


Moopsのドキュメントには次のように書かれています (私のものを強調):

Moops はクラスで MooseX::MungeHas を使用するため、Moose や Mouse を使用している場合でもhas キーワードがMoo 固有の機能をサポートします。具体的にはis => 'rwp'is => 'lazy'builder => 1、 、clearer => 1predicate => 1、および をサポートしていますtrigger => 1

それでは、 Mooを見てみましょう。ドキュメントのhasセクションでは、次のように述べています(私のものを強調してください):

rwp「読み取り/書き込み保護」を表し、 のようなリーダーを生成しますが、クラスの内部から書き込むように設計されているが、外部からは読み取り専用になるように設計された属性に対してroライターを設定します。_set_${attribute_name}この機能は MooseX::AttributeShortcuts から来ています。

では、MooseX::AttributeShortcutsに進みます。

is => 'rwp' を指定すると、次のオプションが設定されます。

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

しかし、これはまさにインスピレーションを受けた場所です。実際にはMethod::Generate::Accessor 1で 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 にフックし、修飾子に少しのロジックを に追加することで、実際に Mooでそれを変更できます。これは、Moose が関与していない限り、Moops では機能しません。aroundgenerate_method

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を使用していることがわかりました。

于 2015-09-24T14:37:50.703 に答える