Category: Modules Keywords: Class::Accessor
prattle
闲着不知道做什么好,就去看模块源码。顺便写些翻译和代码。打算是打算写一个系列,就是不知道我的热情能持续多久了。
诸位若闲着无聊,看看无妨。
今天介绍下 Class::Accessor 和 Class::Accessor::Fast
例子
Class::Accessor - Automated accessor generation/自动化存取器假设我们写一个 People 模块。每个人都有各自属性,比如 age, gender, birthday, occupation, location, salary etc.
经常要用的是获得他们的属性和设置新的属性。
对应的代码为:
sub occupation {
my $self = shift;
if(@_ == 1) {
$self->{occupation} = shift;
} elsif (@_ > 1) {
$self->{occupation} = [@_];
}
return $self->{occupation};
}
sub age {
my $self = shift;
if(@_ == 1) {
$self->{age} = shift;
}
return $self->{occupation};
}
这样我们能用my $occupation = $marry->occupation;来获取marry的职业,而用$marry->occupation('doctor', 'teacher');(假设她早上当医生下午当老师)来设置它的职业。而 gender等其他的属性也要重复这段代码,这样写下来的话代码太冗长而且不符合我们的美德懒惰了。
当然我们有进一步的写法,写一个通用的 set, get 函数:
sub set {
my($self, $key) = splice(@_, 0, 2);
if(@_ == 1) {
$self->{$key} = $_[0];
}
elsif(@_ > 1) {
$self->{$key} = [@_];
}
else {
require Carp;
&Carp::confess("Wrong number of arguments received");
}
}
sub get {
my $self = shift;
if(@_ == 1) {
return $self->{$_[0]};
}
elsif( @_ > 1 ) {
return @{$self}{@_};
}
else {
require Carp;
&Carp::confess("Wrong number of arguments received.");
}
}
这样我们能用 $marry->get('age') 来获取她的年龄,用 $marry->set('age', '33'); 来设置它的年龄。看上去似乎很不错了,但是 marry 的 gender 是 female, 一生下来就定死了的。而我们希望她的 salary 只能写入不能被人读取。
怎么做好呢?打个广告,不妨试试 Class::Accessor
package People;
use base qw(Class::Accessor);
People->mk_accessors(qw(age occupation location));
People->mk_ro_accessors(qw(gender birthday));
People->mk_wo_accessors('salary');
1;
#!/usr/bin/perl
use People;
my $marry = People->new({
'gender' => 'female',
'birthday' => '2005-4-26',
'age' => 1,
});
print $marry->gender;
$marry->salary('100');
$marry->age('2');
print $marry->age; # print 2
# etc ...
# as follow is wrong
# print $marry->salary; # salary is write-only
# $marry->gender('man'); # gender is read-only
非常简单,就三句代码可以定义无数个函数。:)
Class::Accessor && Class::Accessor::Fast
Class::Accessor::Fast 是 Class::Accessor 的缩写版本,它舍弃了 Class::Accessor 中的 set & get (这东西的作用参见 perldoc Class::Accessor ),所以速度更快。一般而言不用自己定制 set,get 的话推荐使用 Class::Accessor::FastClass::DBI 用来 Class::Accessor ,而 Catalyst 用了Class::Accessor::Fast.
Enjoy!