2010-10-22 42 views
6

我正在爲一個駝鹿對象編寫一個模塊。我想允許使用這個對象的用戶(或我自己)根據他/她的需要隨時添加一些字段。我不能先定義這些領域,因爲我根本不知道他們會是什麼。如何靈活地將數據添加到Moose對象?

我現在只是添加了名爲額外的類型hashref這是被設定爲rw單場,這樣用戶就可以簡單地把東西在哈希:

# $obj is a ref to my Moose object  
$obj->extra()->{new_thingie}="abc123"; # adds some arbitrary stuff to the object 
say $obj->extra()->{new_thingie}; 

這工作。但是...這是一種常見的做法嗎?任何其他(可能更優雅)的想法?

注意我不想創建另一個模塊來擴展這個模塊,這真的只是我想要添加的即時模塊。

回答

6

我可能會通過原生特質做這樣的:

has custom_fields => (
    traits  => [qw(Hash)], 
    isa  => 'HashRef', 
    builder => '_build_custom_fields', 
    handles => { 
     custom_field   => 'accessor', 
     has_custom_field  => 'exists', 
     custom_fields  => 'keys', 
     has_custom_fields => 'count', 
     delete_custom_field => 'delete', 
    }, 
); 

sub _build_custom_fields { {} } 

上的對象你會使用這樣的:

my $val = $obj->custom_field('foo');   # get field value 
$obj->custom_field('foo', 23);     # set field to value 

$obj->has_custom_field('foo');     # does a specific field exist? 
$obj->has_custom_fields;      # are there any fields? 

my @names = $obj->custom_fields;    # what fields are there? 
my $value = $obj->delete_custom_field('foo'); # remove field value 

一個常見的用例的東西一樣,這是添加可選內省的數據到異常和消息類。

+0

+1這真的很酷! – 2010-10-22 15:33:33

+0

如果我嘗試閱讀(未設置)不存在的字段,是否可以使存取器發出咔嚓聲? – 2010-10-23 14:35:20

+0

您可以使用around修飾符來包裝'custom_field'訪問器,檢查參數,並在'has_custom_field'返回false時發出呱呱聲。 – phaylon 2010-10-23 16:23:21

4

如果你還沒有使類不可變(有一個performance penalty沒有這樣做,除了我對飛行中改變類定義的擔憂外),你應該可以通過獲取元類該對象(使用$meta = $object->meta)和使用add_attribute方法的Class::MOP::Class

#!/usr/bin/perl 

package My::Class; 

use Moose; 
use namespace::autoclean; 

package main; 

my $x = My::Class->new; 
my $meta = $x->meta; 
$meta->add_attribute(
    foo => (
     accessor => 'foo', 
    ) 
); 

$x->foo(42); 

print $x->foo, "\n"; 

my $y = My::Class->new({ foo => 5 }); 
print $y->foo, "\n"; 

輸出:

42 
5
+0

+1有趣。謝謝。我通常會將課程設置爲不可變的(遵循穆斯最佳實踐)。 – 2010-10-22 13:14:01

3

以防萬一你想一個方法來添加一個對象,而不是整個類,然後看看像MooseX::SingletonMethod

E.g.

use 5.012; 
use warnings; 

{ 
    package Foo; 
    use MooseX::SingletonMethod; 
    sub bar { 'bar' }  # method available to all objects 
} 

my $foo = Foo->new; 

$foo->add_singleton_method(baz => sub { 'baz!' }); 

$foo->baz;  # => baz! 

因此在上面的方法baz僅添加到對象$foo而不是Foo類。

嗯...我想知道我是否可以實現MooseX :: SingletonAttribute?


以前的一些SO回答使用MooseX::SingletonMethod

而且也這篇博客也許使用和/或利息:Easy Anonymous Objects

/I3az/

+0

+1謝謝,很高興瞭解'MooseX :: SingletonMethod'。 – 2010-10-22 13:14:28

相關問題