OO-Perl别名类属性

时间:2010-10-10 04:36:59

标签: perl alias-method

我有一个我正在研究的模块。我正在设置一些这样的属性:

$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 个答案:

答案 0 :(得分:10)

是的,使用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";

答案 1 :(得分:4)

我会建议Moose超过你正在做的事情,但最容易实现你所要求的方法可能就是:

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

这样,Foo是否自动加载并不重要。

答案 2 :(得分:0)

非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;

现在foofu访问相同的内容:

Foo is now 5
Foo is now 9
Fu is now 9
Fu is set to 17
Foo is now 17