Атрибуты класса OO-Perl Aliasing
У меня есть модуль, над которым я работаю. Я настраиваю несколько таких атрибутов:
$self->{FOO};
$self->{BAR};
$self->{FOOBAR};
И я хочу использовать AUTOLOAD, чтобы помочь создать методы для доступа к этим атрибутам. Например, $foo->Bar()
возвращает значение $self->{BAR}
, Нет проблем. Все стандартно.
Теперь я хочу создать псевдоним методы. Например, если кто-то говорит $obj->Fu();
Я вернусь $self->{FOO}
, Что я хотел бы сделать, это создать $self->{FU}
это указывает на то же место в памяти, что и $self->{FOO}
, Таким образом, когда я устанавливаю значение $self->{FOO}
, $self-{FU}
также установлен. Таким образом, мне не нужно вносить всевозможные изменения в работу AUTOLOAD или не забудьте установить $self->{FU}
всякий раз, когда я устанавливаю $self->{FOO}
,
Есть ли простой способ сделать это?
3 ответа
Да, используйте Moose, а не пытайтесь сделать явное отображение между ключами хеша. Написание собственных средств доступа или использование AUTOLOAD не является необходимым и имеет гораздо более высокую вероятность ошибки:
package MyClass;
use Moose;
use MooseX::Aliases;
has foo => (
is => 'rw', isa => 'Str',
alias => 'fu',
);
has bar => (
is => 'rw', isa => 'Str',
);
__PACKAGE__->meta->make_immutable;
no Moose;
1;
package main;
use strict;
use warnings;
use MyClass;
my $obj = MyClass->new;
$obj->foo("value");
$obj->fu("a new value");
# prints "foo has the value 'a new value'"
print "foo has the value '", $obj->foo, "'\n";
Я бы порекомендовал Moose о том, что вы делаете, но самый простой способ выполнить то, что вы спрашиваете, это, вероятно, это:
sub Fu { shift->Foo(@_) }
Таким образом, не имеет значения, если Foo
загружается или нет.
Решение не Moose - просто создать псевдоним в таблице символов. Это не обычное дело, и я подозреваю, что все, что вы пытаетесь сделать, имеет лучший способ, лось или нет. Не используйте ничего из этого, если вы можете избежать этого с помощью лучшего дизайна или интерфейса, которые часто являются превосходными решениями для подобных вещей.
В этом AUTOLOAD
рутина, я смотрю на %Aliases
хэш, чтобы выяснить другие методы, еще я должен определить. Когда у меня есть псевдонимы, я делаю правильные псевдонимы в таблице символов. Это немного уродливо, но избегает добавления еще одного фактического метода в стек вызовов:
#!perl
use 5.010;
{
package SomeClass;
use Carp;
use vars qw($AUTOLOAD);
sub new {
return bless {
map { $_, undef } qw(FOO BAR FOOBAR)
}, $_[0];
};
my %Aliases = (
FOO => [ qw(fu) ],
);
sub AUTOLOAD {
our $method = $AUTOLOAD;
$method =~ s/.*:://;
carp "Autoloading $method";
{
no strict 'refs';
*{"$method"} = sub {
@_ > 1
?
$_[0]->{"\U$method"} = $_[1]
:
$_[0]->{"\U$method"}
};
foreach my $alias ( @{ $Aliases{"\U$method"} } ) {
*{"$alias"} = *{"$method"};
}
goto &{"$method"};
}
}
sub DESTROY { 1 }
}
my $object = SomeClass->new;
$object->foo(5);
say "Foo is now ", $object->foo;
say "Foo is now ", $object->foo(9);
say "Fu is now ", $object->fu;
say "Fu is set to ", $object->fu(17);
say "Foo is now ", $object->foo;
Сейчас foo
а также fu
получить доступ к тому же:
Foo is now 5
Foo is now 9
Fu is now 9
Fu is set to 17
Foo is now 17