2012-04-13 153 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