2012-04-13 217 views
0

在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); 
} 
+0

我认为串行器可以调用访问器。没有访问者调用我可以看到的序列化程序的危险。 – Schwern 2012-04-13 02:50:48

+0

唯一的问题,我与那是在某些情况下,我将取消定义读者... – xenoterracide 2012-04-13 03:22:08

回答

0

我的问题似乎是两倍,我的匿名子例程没有做对,我需要通过的实例该对象指向匿名子例程。

这似乎在我的驼鹿扩展

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'; 
}; 

我想我可以活过去的实例,虽然我不完全是sur e为什么get_value需要。

+0

'get_value()'需要该实例的原因是因为这是数据保存的位置,这就是*实例*。它是绑定到一个类的数据。这也不是真正的卷曲。你只是创建一个匿名的子类,currying涉及的不止是这个(你必须创建一个关于一个或多个值的闭包,而你在这里我没有任何地方可以做到这一点)。 – perigrin 2012-04-13 05:22:14

+0

是的,但我会认为$ attr-> get_value是属性的一个实例... – xenoterracide 2012-04-13 05:33:03

+1

你混淆了你的对象实例。 '$ attr'不是'Test'的一个实例,它是'Moose :: Meta :: Attribute'的一个实例。它仍然需要传递给它的适当的数据结构(在这种情况下是'Test'的实例),以便它能挖掘出适当的值。 – perigrin 2012-04-13 05:49:41