Атрибуты класса OO-Perl Aliasing - PullRequest
2 голосов
/ 10 октября 2010

У меня есть модуль, над которым я работаю. Я настраиваю несколько таких атрибутов:

$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 ]

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

Да, используйте 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";
4 голосов
/ 10 октября 2010

Я бы порекомендовал Лось за то, что вы делаете, но самый простой способ выполнить то, что вы спрашиваете, это, вероятно, это:

sub Fu { shift->Foo(@_) }

Таким образом, не имеет значения, загружен Foo или нет.

0 голосов
/ 11 октября 2010

Решение не для 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
...