Подтвердить что ты не робот

Как я могу создать внутренние (частные) переменные объекта Moose (атрибуты)?

Я бы хотел, чтобы некоторые атрибуты (возможно, это неправильный термин в этом контексте) были частными, то есть только внутренними для использования объекта - не могут быть прочитаны или записаны извне.

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

Где и как определить такую ​​переменную?

4b9b3361

Ответ 1

Moose::Manual::Attributes показывает следующий способ создания частных атрибутов:

has '_genetic_code' => (
   is       => 'ro',
   lazy     => 1,
   builder  => '_build_genetic_code',
   init_arg => undef,
);

Настройка init_arg означает, что этот атрибут не может быть установлен в конструкторе. Сделайте это rw или добавьте writer, если вам нужно его обновить.

/I3az/

Ответ 2

Вы можете попробовать что-то вроде этого:

has 'call_counter' => (
    is     => 'ro',
    writer => '_set_call_counter',
);

is => 'ro' делает атрибут только для чтения. Moose генерирует геттер. Ваши методы будут использовать getter для увеличения значения, например:

sub called {
    my $self = shift;
    $self->_set_call_counter( $self->call_counter + 1 );
    ...
}

writer => '_set_call_counter' генерирует установщик с именем _set_call_counter. Лось не поддерживает истинные частные атрибуты. Внешний код может, технически, вызвать _set_call_counter. Однако, по соглашению, приложения не вызывают методы, начинающиеся с подчеркивания.

Ответ 3

Я думаю, что вы хотите MooseX:: Privacy.

Perldoc сообщает вам все, что вам нужно - это добавляет новую черту к вашим атрибутам, позволяя объявить их как конфиденциальными или защищенными:

has config => (
    is     => 'rw',
    isa    => 'Some::Config',
    traits => [qw/Private/],
);

Ответ 4

Алан У. Смит предоставил переменную частного класса с лексической переменной, но она разделяется всеми объектами класса. Попробуйте добавить новый объект в конец примера script:

my $c1 = CountingObject->new();
printf( "%s\n", $c1->get_count() );
#  also shows a count of 10, same as $co

Использование MooseX: конфиденциальность - хороший ответ, хотя, если вы не можете, вы можете одолжить трюк из лагеря объектов с наивысшими возможностями:

package CountingObject;

use Moose;

my %cntr;

sub BUILD { my $self = shift; $cntr{$self} = 0 }

sub add_one { my $self = shift; $cntr{$self}++; }

sub get_count { my $self = shift; return $cntr{$self}; }

1;

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

package CountingObject;

use Moose;

my %cntr;

sub add_one { $cntr{$_[0]}++ }

sub get_count { return $cntr{$_[0]}||0 }

1;

Ответ 5

Мне не удалось выяснить, как сделать атрибуты Moose полностью закрытыми. Всякий раз, когда я использую has 'name' => (...); для создания атрибута, он всегда подвергается чтению как минимум. Для элементов, которые я хочу быть действительно частными, я использую стандартные "мои" переменные внутри пакета Moose. Для быстрого примера возьмите следующий модуль "CountingObject.pm".

package CountingObject;

use Moose;

my $cntr = 0;

sub add_one { $cntr++; }

sub get_count { return $cntr; }

1;

Сценарии, которые используют этот модуль, не имеют прямого доступа к переменной $cntr. Они должны использовать методы "add_one" и "get_count", которые действуют как интерфейс для внешнего мира. Например:

#!/usr/bin/perl 

### Call and create
use CountingObject;
my $co = CountingObject->new();

### This works: prints 0
printf( "%s\n", $co->get_count() );

### This works to update $cntr through the method
for (1..10) { $co->add_one(); }

### This works: prints 10
printf( "%s\n", $co->get_count() );

### Direct access won't work. These would fail:
# say $cntr;
# say $co->cntr;

Я новичок в Moose, но, насколько я могу судить, этот подход обеспечивает полностью частные переменные.