OO-Perl 类属性别名

发布于 2024-09-26 11:50:27 字数 601 浏览 4 评论 0原文

我有一个正在开发的模块。我正在设置一些如下属性:

$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->{ 时记住设置 $self->{FU} FOO}

有什么简单的方法可以做到这一点吗?

I have a module that I'm working on. I am setting up a few attributes like this:

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

And, I want to use AUTOLOAD to help create methods for accessing these attributes. For example, $foo->Bar() returns the value of $self->{BAR}. No problem. Everything is standard.

Now, I want to create alias Methods. For example, if someone says $obj->Fu();, I'll return $self->{FOO}. What I'd like to do is create a $self->{FU} that points to the same memory location as $self->{FOO}. That way, when I set the value of $self->{FOO}, $self-{FU} is also set. This way, I don't have to make all sorts of changes in the way AUTOLOAD works or remember to set $self->{FU} whenever I set $self->{FOO}.

Any easy way of doing this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

巾帼英雄 2024-10-03 11:50:27

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

Yes, use Moose, rather than attempting to make explicit mapping between hash
keys. Writing your own accessors, or using AUTOLOAD, is not necessary and has
a much higher chance of error:

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";
美胚控场 2024-10-03 11:50:27

我会推荐 Moose 超过你正在做的事情,但这是完成你正在做的事情的最简单方法询问可能是这样的:

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

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

I would recommend Moose over what you're doing, but the easiest way to accomplish what you're asking is probably this:

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

This way, it doesn't matter if Foo is autoloaded or not.

没︽人懂的悲伤 2024-10-03 11:50:27

非 Moose 解决方案是在符号表中创建一个别名。这不是一件常见的事情,而且我怀疑无论你想做什么,都有更好的方法,无论是 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

The non-Moose solution is to just create an alias in the symbol table. It's not a common thing to do, and I suspect that whatever you are trying to do has a better way, Moose or otherwise. Don't use any of this if you can avoid it with a better design or interface, which are often the superior solutions to things like this.

In this AUTOLOAD routine, I look at a %Aliases hash to figure out other methods else I have to define. When I have aliases, I make proper aliases in the symbol table. It's a bit ugly, but it avoids adding another actual method in the call stack:

#!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;

Now foo and fu access the same thing:

Foo is now 5
Foo is now 9
Fu is now 9
Fu is set to 17
Foo is now 17
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文