Изменение префикса писателя, когда (is => "rwp")
Если я хочу изменить защищенный от записи атрибут т.е.
use Moops;
class foo {
has attr => (is => "rwp");
}
нужно использовать _set_attr()
,
Можно ли изменить это на _attr()
без использования явного writer
?
Пытался use MooseX::::AttributeShortcuts -writer_prefix => 'prefix';
но это не сработало.
1 ответ
Нет, вам нужно сделать это самостоятельно, установив writer
,
TLDR: Внизу есть патч обезьяны, чтобы сделать это в любом случае.
Документы Moops говорят (подчеркивает мое):
Moops использует MooseX::MungeHas в ваших классах, так что ключевое слово has поддерживает некоторые специфичные для Moo функции, даже когда вы используете Moose или Mouse. В частности, он поддерживает
is => 'rwp'
,is => 'lazy'
,builder => 1
,clearer => 1
,predicate => 1
, а такжеtrigger => 1
,
Теперь давайте посмотрим на Му. в has
В разделе документа написано (подчеркивает мой):
rwp
расшифровывается как "защищено от чтения и записи" и генерирует читателя какro
, но также устанавливает писателя_set_${attribute_name}
для атрибутов, которые предназначены для записи внутри класса, но только для чтения извне. Эта функция взята из MooseX::AttributeShortcuts.
Хорошо, перейдем к https://metacpan.org/pod/MooseX::AttributeShortcuts:
Указание is => 'rwp' приведет к установке следующих параметров:
is => 'ro' writer => "_set_$name"
Тем не менее, это только то, где это было вдохновлено. На самом деле это реализовано в Moo в Method::Generate::Accessor 1.
} elsif ($is eq 'rwp') { $spec->{reader} = $name unless exists $spec->{reader}; $spec->{writer} = "_set_${name}" unless exists $spec->{writer}; } elsif ($is ne 'bare') {
И даже более того, это не то, что делается в Moops. Фактически, это происходит в MooseX::MungeHas, который использует Moops, но только если вызывающий не Moo:
push @code, ' if ($_{is} eq q(rwp)) {'; push @code, ' $_{is} = "ro";'; push @code, ' $_{writer} = "_set_$_" unless exists($_{writer});'; push @code, ' }';
Выглядит довольно ясно Это в сгенерированном коде. Приведенное ниже решение может работать, если оно использует только Moo, но я не знаю, как это заставить.
Вы действительно можете изменить это в Moo, подключившись к Method::Generate::Accessor Moo, используя Class::Method::Modifiers и добавив немного логики в around
модификатор к generate_method
, Это не работает, работает для Moops, пока в Moose не участвуют.
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.