Как создать пользовательское средство доступа для записи при использовании Moose?

Изменить: ответ добавлен ниже, вопрос оставлен здесь только для исторических целей.

В документации Moose указано, что:

При желании вы также можете явно указать имена методов, которые будут использоваться для чтения и записи значения атрибута. Это особенно удобно, когда вы хотите, чтобы атрибут был общедоступным для чтения, но только для частной установки. Например:

has 'weight' => (
  is     => 'ro',
  writer => '_set_weight',   
 );

Это может быть полезно, если вес рассчитывается на основе других методов. Например, каждый раз, когда вызывается метод eat, мы можем корректировать вес. Это позволяет нам скрыть детали реализации изменений веса, но по-прежнему предоставлять значение веса пользователям класса.

На основе этого примера я написал следующий код:

has '_current_url' => (
    is => 'ro',
    isa => 'URI',
    writer => '_write_URI_to_current_url',
);

# Thus we ensure only a URI object gets written to current_url always
sub _current_url
{
    my $self = shift;
    $self->_write_URI_to_current_url(URI->new_abs($_[0], $self->start_url));
}

Мое намерение состояло в том, чтобы гарантировать, что установка current_url всегда устанавливает объект URI, даже если он вызывается с простой строкой. Однако, когда я пытаюсь запустить код, я получаю:

Невозможно присвоить значение доступному только для чтения методу доступа _current_url

в том месте (в моем классе), где я пытаюсь установить current_url (с $self->_current_url($str);).

Это мой второй день с Мусом, поэтому я совершенно не понимаю, что здесь происходит. Насколько я понимаю, is => 'ro' только просит Moose не создавать средство доступа записи по умолчанию с тем же именем, что и у атрибута, правильно ли это понимание? Как я могу достичь своей цели здесь?


person sundar - Remember Monica    schedule 30.08.2013    source источник
comment
Для того, что вы здесь делаете, вам действительно нужно исследовать типы и приведения типов. Вам не нужен пользовательский писатель, вам нужно настраиваемое принуждение.   -  person cjm    schedule 31.08.2013
comment
@cjm Coercion - это первое, что я попробовал, но проблема в том, что изменение типа via зависит от второго параметра $self->start_url, который Moose не понравился, поэтому это привело к ошибке. Получает ли подпрограмма в via копию $self, и можно ли использовать другой атрибут для принуждения?   -  person sundar - Remember Monica    schedule 31.08.2013


Ответы (2)


Хорошо, я считаю, что нашел проблему.

Метод _current_url, который я вставил выше, был переопределен сгенерированным Moose методом доступа только для чтения с тем же именем, поэтому, когда я попытался вызвать $self->_current_url со значением, он выдает указанную выше ошибку, указывающую, что метод доступа только для чтения не может устанавливать значения.

Я предполагаю, что в идеале сообщение об ошибке должно быть Cannot assign a value **through** a read-only accessor of _current_url, а не **to** a read-only accessor.

Изменение имени сабвуфера на _set_current_url решило проблему. Я предполагаю, что другим способом добиться того же было бы сказать Мусу, что _current_url is => 'rw', а затем создать файл around '_current_url'. Я не пробовал этот подход.

person sundar - Remember Monica    schedule 30.08.2013

Поздно в игру, но только что увидел этот пост и столкнулся с тем же самым некоторое время назад. '_set_current_url' действительно кажется средством доступа к атрибуту, а не атрибутом. Возможно, стоит рассмотреть:

has '_current_url' => {
  is => 'rw',
  isa => 'URI',
  writer => 'set_current_url',
  reader => 'get_current_url'
  }

Это немного чище, поскольку атрибут является исходным «_current_url», и у вас есть средства доступа для получения/установки атрибута.

person Richard    schedule 02.01.2014
comment
Насколько я понимаю, параметры writer и reader изменяют имя автоматически созданных средств доступа, это неправильно? Если это правильно, то автоматическое создание модуля записи с именем set_current_url в данном случае не кажется полезным, поскольку суть заключается в настройке средства доступа к записи, я что-то упустил? - person sundar - Remember Monica; 02.01.2014
comment
Автоматически созданный метод доступа — «_current_url». Если вы удалите «писатель» и «читатель» из оператора «has», вы можете получить/установить атрибут, используя «_current_url» (т. е. $object-›_current_url). Когда вы используете писатель/читатель, он отключает доступ к атрибуту с «_current_url» и требует, чтобы вы использовали «set_current_url» и «get_current_url». - person Richard; 03.01.2014