26 April 2005
This post may be outdated due to it was written on 2005. The links may be broken. The code may be not working anymore. Leave comments if needed.

prattle

闲着不知道做什么好,就去看模块源码。顺便写些翻译和代码。
打算是打算写一个系列,就是不知道我的热情能持续多久了。
诸位若闲着无聊,看看无妨。
今天介绍下 Class::AccessorClass::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::Fast
Class::DBI 用来 Class::Accessor ,而 Catalyst 用了Class::Accessor::Fast.

Enjoy!



blog comments powered by Disqus