2

作業中のモジュールがあります。私はこのようないくつかの属性を設定しています:

$self->{FOO};
$self->{BAR};
$self->{FOOBAR};

そして、AUTOLOADを使用して、これらの属性にアクセスするためのメソッドを作成したいと思います。たとえば、$foo->Bar()の値を返します$self->{BAR}。問題ない。すべてが標準です。

次に、エイリアスメソッドを作成します。たとえば、誰かが言った場合$obj->Fu();、私は戻り$self->{FOO}ます。私がやりたいのは$self->{FU}、と同じメモリ位置を指すを作成すること$self->{FOO}です。そうすれば、の値を設定すると$self->{FOO}$self-{FU}も設定されます。$self->{FU}このように、AUTOLOADの動作方法にあらゆる種類の変更を加える必要はなく、設定するたびに設定することを忘れないで$self->{FOO}ください。

これを行う簡単な方法はありますか?

4

3 に答える 3

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";
于 2010-10-10T05:03:02.757 に答える
4

あなたがしていることよりもMooseをお勧めしますが、あなたが求めていることを達成する最も簡単な方法はおそらくこれです:

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

このように、が自動ロードされるかどうかFooは問題ではありません。

于 2010-10-10T05:10:08.853 に答える
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;

次に、同じものfooにアクセスします。fu

Foo is now 5
Foo is now 9
Fu is now 9
Fu is set to 17
Foo is now 17
于 2010-10-11T18:29:59.230 に答える