我经常使用Moose
来确保我的数据具有合适的默认值,例如:
package Bla;
use Moose;
has eins => is => 'ro', isa => 'Int';
has zwei => is => 'ro', isa => 'Int', default => 2;
no Moose; __PACKAGE__->meta->make_immutable;
package main;
use v5.10;
use Data::Dumper;
use URI;
my $bla = Bla->new( eins => 77 );
my $bl2 = Bla->new;
print Dumper $bla, $bl2;
say join "\t", %$bla;
say join "\t", %$bl2;
my $u = URI->new( 'http://www.example.com/ws' );
$u->query_form( %$bla );
say $u;
$u->query_form( %$bl2 );
say $u;
只要那种数据容器没有任何引用成员(因此没有嵌套),你会说如果你想要只使用%$object
中的对象哈希表是可以的,或者是值得推荐的吗?为了得到原始数据,让我们说通过URI->query_form
或类似的方法作为序列化的初始化器?或者有没有更好的方法来实现这个内置于穆斯?
更新
通过在上面的行,标题,甚至标签中删除序列化这个小词,我看起来一直在引导人们走错路。请注意,我对查找序列化程序不感兴趣。在我的示例中,URI
模块是序列化程序。问题是如何获取数据以提供URI->query_form
(或我可能尝试的任何其他序列化程序)。所以我想知道的是,对于给定的Moose对象$object
是否可以通过仅取消引用对象引用来获取数据(键和值,或者,如果您愿意,还可以获取属性名称和值),如%$object
?只要对象不包含任何引用值(如数组引用,其他对象等)以及 - 我不确定的事情 - Moose赢了,如果我迄今为止收集的经验是可行的,这将有效。不要使用实例引用来存储自己的数据,例如__MOOSE_WHATNOT => $funky_moose_addon
。那么Moose可能会使用实例引用来存储它自己的一些数据,还是被设计排除?
更新2
回答标题中的问题:
不,使用%$object
来获取Moose对象的数据并不是好的,即使它不包含任何参考值,所以你得到的副本组成$object
的字符串和数字。这不好,因为它破坏了封装。它甚至可能导致运行时错误,因为虽然散列是构成Moose对象基础的默认数据结构,但不能保证它总是一个散列,实际上它可能是其他东西。
您应该使用MooseX::Storage
代替,这将为对象提供pack
方法。
答案 0 :(得分:5)
驼鹿“本地”的方式是使用MooseX::Storage类的一组。
答案 1 :(得分:5)
正如jira所说,规范的方法是使用MooseX::Storage
。 %$对象的问题在于,虽然Moose对象实例的默认存储是一个有福的哈希,但Moose没有做出正式的承诺,总是如此。例如,MooseX :: GlobRef,MooseX :: NonMoose,MooseX :: InsideOut都允许使用替代实例结构。
像MooseX :: Storage这样的软件包使用MOP来查询实例元对象并正确地序列化数据结构。你当然可以通过抓取每个Moose对象后面的Moose :: Meta :: Class来手工完成这个,但老实说MooseX::Storage
编写得非常好并且此时非常稳定。
标准用法是:
package Class {
use Moose;
use MooseX::Storage;
with Storage();
...
}
my $o = Class->new(...)
my $u = URI->new( 'http://www.example.com/ws' );
$u->query_form( $o->pack );