Используя Moose, как мне установить значение атрибута ro в атрибуте runtime?

У меня есть атрибут атрибута, который я хочу установить на основе других атрибутов класса. Я действительно хочу по умолчанию для Attribute Trait, который получает копию класса $self а не мета для атрибута. Я хочу сделать что-то подобное в своем классе:

after 'BUILD' => sub {                                                     
  my $self = shift;                                                        
  $self->meta->get_attribute('id')->column_name( $self->_unique_key_name );
};  

Но я хочу сохранить свой атрибут RO? Это возможно. Я знаю, что MOP позволяет установить значение атрибута класса, но я не могу понять, как установить атрибут в метаатрибуте.

1 ответ

Это звучит как очень странный дизайн (зачем метаклассу нужен экземпляр класса, который он описывает?) - но вы можете сделать это достаточно легко, используя метакласс метакласса (помните, что метаслассы Moose загружаются с помощью MOP сам):

$self->meta->meta->get_attribute("foo")->default($some_value);

Также помните, что значения по умолчанию должны быть помещены в coderef, если они сами являются ссылками: $some_value = sub { $instance };


На самом деле, это не будет работать - "по умолчанию" только для чтения. Вместо того, чтобы возиться с MOP на таком низком уровне, я бы посоветовал вам пересмотреть свой дизайн - например, сохранить свой "default" в другом атрибуте и написать подпрограмму по умолчанию, делегированную ему:

package MyApp::Meta::Attribute::Trait::Foo;

# set at runtime, when we have an instance to store here
has _default_of_foo => (
    is => 'rw', isa => 'Object',
);
has foo => (
    is => 'ro', isa => 'Object',
    lazy => 1,
    default => sub { shift->_default_of_foo },
);
Другие вопросы по тегам