Как я могу создать внутренние (частные) переменные объекта Moose (атрибуты)? - PullRequest
18 голосов
/ 22 октября 2010

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

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

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

Ответы [ 5 ]

15 голосов
/ 22 октября 2010

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

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

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

/ I3az /

10 голосов
/ 22 октября 2010

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

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

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

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

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

7 голосов
/ 28 января 2012

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

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

has config => (
    is     => 'rw',
    isa    => 'Some::Config',
    traits => [qw/Private/],
);
3 голосов
/ 14 марта 2012

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

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;
2 голосов
/ 28 января 2012

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

...