書き込み保護属性を変更したい場合。
use Moops;
class foo {
has attr => (is => "rwp");
}
使用する必要があります_set_attr()
。
_attr()
explicit を使用せずにそれを変更することは可能writer
ですか?
試してみuse MooseX::::AttributeShortcuts -writer_prefix => 'prefix';
ましたが、うまくいきませんでした。
書き込み保護属性を変更したい場合。
use Moops;
class foo {
has attr => (is => "rwp");
}
使用する必要があります_set_attr()
。
_attr()
explicit を使用せずにそれを変更することは可能writer
ですか?
試してみuse MooseX::::AttributeShortcuts -writer_prefix => 'prefix';
ましたが、うまくいきませんでした。
いいえ、 を設定して自分で行う必要がありますwriter
。
TLDR: 一番下には、とにかくそれを行うためのモンキー パッチがあります。
Moopsのドキュメントには次のように書かれています (私のものを強調):
Moops はクラスで MooseX::MungeHas を使用するため、Moose や Mouse を使用している場合でもhas キーワードがMoo 固有の機能をサポートします。具体的には
is => 'rwp'
、is => 'lazy'
、builder => 1
、 、clearer => 1
、predicate => 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 では機能しません。around
generate_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を使用していることがわかりました。