Таким образом, я знаком с полевой прагмой в Perl, который может использоваться для ограничения полей, которые хранятся в классе:
package Fruit;
use fields qw( color shape taste );
sub new {
my ( $class, $params ) = @_;
my $self = fields::new( $class ) unless ref $class;
foreach my $name ( keys %$params ) {
$self->{ $name } = $params->{ $name };
}
return $self;
}
После того как я объявил поля наверху, как я могу вернуть список, сказать, потому что я хочу генерировать средства доступа динамично? keys %FIELDS
единственный путь?
Во вторую очередь существует ли более эффективный способ предварительно заполнить поля в конструкторе, чем цикличное выполнение через и присваивающий каждый параметр, как я делаю выше?
Если вы работаете в Perl 5.10 и выше (на самом деле 5.9 и выше, но я не считаю релизы разработчиков), fields
создает ограниченный хэш. См. Hash::Util для получения информации об ограниченных хэшах.
Чтобы получить все поля, доступные для ограниченного хэша, используйте функции legal_keys
или legal_ref_keys
:
use Hash::Util qw( legal_ref_keys );
my $froot = Fruit->new();
my @attribs = legal_ref_keys($froot);
Вы можете сделать несколько вещей для автоматической генерации ваших методов:
%FIELDS
в модуле для генерации методов во время компиляции или через AUTOLOAD. MORE PROBLEMS - предполагает, что неопубликованный бит прагмы fields
останется. Вариант 4:
package Fruit;
use strict;
use warnings;
my @ATTRIBUTES;
BEGIN { @ATTRIBUTES = qw( color shape taste ); }
use fields @ATTRIBUTES;
for my $attrib ( @ATTRIBUTES ) {
my $getset = sub {
my $self = shift;
if( @_ ) {
$self->{$attrib} = shift;
}
return $self->{$attrib};
};
{ no strict 'refs';
*{$attrib} = $getset;
}
}
sub new {
my ( $class, $params ) = @_;
my $self = fields::new( $class ) unless ref $class;
foreach my $name ( keys %$params ) {
$self->{ $name } = $params->{ $name };
}
return $self;
}
Вариант 5.
package Fruit;
use Moose;
has 'color' => (
is => 'rw',
isa => 'Str',
);
has 'shape' => (
is => 'rw',
isa => 'Str',
);
has 'taste' => (
is => 'rw',
isa => 'Str',
);
Прямо сейчас лучшее рабочее решение, которое у меня есть, это что-то вроде этого:
# Return the fields for this object
sub fields {
my ( $self ) = @_;
my $class = ref( $self ) || $self;
return [ keys %{ "${class}::FIELDS" } ];
}
Каждый объект, созданный с использованием прагмы fields
, будет иметь эти поля (и только эти поля), даже если вы их не инициализируете. Таким образом, вам не нужно беспокоиться о том, что таблица %FIELDS
устарела.
DB<1> $apple = Fruit->new( {qw(color red shape apple taste like-an-apple)} )
DB<2> p join' ',keys %$apple
color taste shape
DB<3> $kiwi = Fruit->new()
DB<4> p join' ',keys %$kiwi
color taste shape