Я думаю, вы действительно хотите, чтобы allowed_values
была отдельной структурой данных с желаемыми свойствами эффективности и упорядоченности. Так как не похоже, что вы заботитесь о заказе, почему бы и нет:
has 'allowed_values' => (
traits => ['Hash'],
isa => HashRef[Bool],
default => sub { +{} },
handles => {
_add_allowed_value => 'set',
remove_allowed_value => 'delete',
value_is_allowed => 'exists',
allowed_values => 'keys',
},
);
method add_allowed_value(Str $value){
$self->_add_allowed_value( $value, 1 );
}
В общем, все, что не относится к реализуемому классу, должно быть реализовано в другом месте. Создание более быстрого времени поиска для массивов не является задачей любого класса, который вы пишете, поэтому он должен быть реализован в другом месте, и этот класс должен использовать этот класс. (В простом случае, как вышеописанный хеш, возможно, можно игнорировать это правило. Но если бы оно было более сложным, вы бы определенно захотели его разложить.)
Edit:
Если вы хотите, чтобы пользователь думал, что это список, как насчет:
use MooseX::Types::Moose qw(Bool ArrayRef HashRef);
use MooseX::Types -declare => ['ListHash'];
subtype ListHash, as HashRef[Bool];
coerce ListHash, from ArrayRef, via { +{ map { $_ => 1 } @$_ } };
has 'allowed_values' => (
# <same as above>
isa => ListHash,
writer => 'set_allowed_values',
coerce => 1,
);
Теперь вы можете установить allowed_values
как:
my $instance = Class->new( allowed_values => [qw/foo bar/] );
$instance->set_allowed_values([qw/foo bar baz/]);
И получить к ним доступ как:
my @allowed_values = $instance->allowed_values;
... if $instance->value_is_allowed('foo');
И изменить их:
$instance->remove_allowed_value('foo');
$instance->add_allowed_value('gorch');
Это скрывает все основные детали реализации от пользователя.
Кстати, строит ли хеш фактически и использует ли его значительно быстрее, чем линейное сканирование по 3 элементам?