【问题标题】:Get an attributes value from within the attribute从属性中获取属性值
【发布时间】:2012-04-13 01:23:56
【问题描述】:

在我正在编写的 Moose 扩展中,我试图从属性中访问属性值,而不通过访问器,但我似乎无法做到这一点。

我正在努力编写这段代码

{
    package Test;
    use Moose;
    use MooseX::RemoteName; #provides magic

    has attr0 => (
        isa         => 'Bool',
        is          => 'ro',
        default     => sub { 1 },
        serializer  => sub {
           my $s = shift;
           return $s->get_value( $s ) ? 'Y' : 'N';
        }, 
    );

    has attr1 => (
       isa => 'Str',
       is  => 'ro',
    )
}

这样我就可以做(从我的测试中)

my $t0 = Test->new({ attr1 => 'foo' });

isa_ok my $attr0 = $t0->meta->get_attribute('attr0'), 'Class::MOP::Attribute';
is $attr0->serialized,  'Y',    'remote_name serializes';

isa_ok my $attr1 = $t0->meta->get_attribute('attr1'), 'Class::MOP::Attribute';
is $attr1->serialized,  'foo',    'remote_name serializes'; # undef

这就是我在扩展中尝试的内容

has serializer => (
    isa       => 'CodeRef',
    is        => 'ro',
    lazy      => 1,
    default   => sub {
        return sub {
            my $arg = shift;
            return $arg->get_value( $arg->associated_class );
        }
    },
);

sub serialized {
    my $self = shift;

    my $coderef = $self->serializer;

    return &$coderef( $self );
}

【问题讨论】:

  • 我认为序列化程序可以调用访问器。访问器调用我可以看到的序列化程序没有危险。
  • 我唯一的问题是,在某些情况下我会取消定义阅读器...

标签: perl metaprogramming moose


【解决方案1】:

我的问题似乎有两个方面,我的匿名子例程没有正确完成,我需要将对象的实例传递给匿名子例程。

这似乎在我的 Moose 扩展中工作

has serializer => (
    predicate => 'has_serializer',
    traits    => ['Code'],
    is        => 'ro',
    default   => sub {
        return sub {
            my ( $self, $instance ) = @_;
            return $self->get_value( $instance );
        }
    },
    handles   => {
        serializing => 'execute_method',
    },
);

sub serialized {
    my ( $self, $instance ) = @_;

    return $self->serializing( $instance );
}

然后允许我编写以下内容(略有不同)

package Test;
use Moose;
use MooseX::RemoteName;

has attr0 => (
    isa        => 'Bool',
    is         => 'ro',
    lazy       => 1,
    default    => sub { 1 },
    serializer => sub {
        my ( $attr, $instance ) = @_;
        return $attr->get_value( $instance ) ? 'Y' : 'N';
    },
);

它将毫无问题地通过此测试

subtest t0 => sub {
    my $t = Test->new;

    is $t->attr0, 1, 'attr0 is 1';

    isa_ok my $attr0 = $t->meta->get_attribute('attr0'), 'Class::MOP::Attribute';

    is $attr0->serialized( $t ),  'Y',    'attr0 serializes';
    isa_ok $t, 'Test';
};

我认为我可以将实例传递进去,尽管我不完全确定为什么 get_value 需要这样做。

【讨论】:

  • get_value() 需要实例的原因是因为这是保存数据的地方,这就是 instance 的意义......它是绑定到类的数据。这也不是真正的咖喱。你只是在创建一个匿名子,currying 涉及的远不止这些(你必须在一个或多个值上创建一个闭包,我可以告诉你,你没有在这里做任何地方)。
  • 您混淆了您的对象实例。 $attr 不是Test 的实例,它是Moose::Meta::Attribute 的实例。它仍然需要将正确的数据结构传递给它(在这种情况下为Test 的实例),以便它可以挖掘出正确的值。
猜你喜欢
  • 2016-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-05
  • 2013-05-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多