コンストラクタとアクセサ自動生成

CLASS
Class::Accessor
Class::Fields

を使います。

以下例、

MyClass.pm


package MyClass;
use strict;
use warnings;
use base qw(Class::Accessor Class::Fields);
use CLASS;
use fields qw( name job _mail );
CLASS->mk_accessors(CLASS->show_fields('Public'));
1;

これだけでMyClassのコンストラクタとfieldsで定義したものへの
アクセサを作ってくれます。便利。

例えばこんな感じで使います。


#! /usr/bin/perl
use strict;
use warnings;
use MyClass;
my $c = MyClass->new;
$c->name('nekokak');
print $c->name,"\n";
$c->job('SE');
print $c->job,"\n";

Class::Fieldsでは_で始まるフィールドはプライベートメソッドとして取り扱われ、
show_fields('Public')メソッドではパブリックなフィールド(_で始まらないフィールド)
が取れてくるので、

CLASS->mk_accessors(CLASS->show_fields('Public'));

とMix-inすることによって
パブリックなフィールドだけアクセサを作ってくれます。

で、Class::Accessor中身がどんな実装になってるか気になったので、
見てみますた。

コアな部分ってこんなのでした。


# Build a closure around $field.
return sub {
my $self = shift;
if(@_) {
return $self->set($field, @_);
}
else {
return $self->get($field);
}
};
sub set {
my($self, $key) = splice(@_, 0, 2);
if(@_ == 1) {
$self->{$key} = $_[0];
}
elsif(@_ > 1) {
$self->{$key} = [@_];
}
else {
$self->_croak("Wrong number of arguments received");
}
}
sub get {
my $self = shift;
if(@_ == 1) {
return $self->{$_[0]};
}
elsif( @_ > 1 ) {
return @{$self}{@_};
}
else {
$self->_croak("Wrong number of arguments received");
}
}

ところで、$self->{'name'}見たいに、インスタンスフィールドに
データを持たせる方法ってどうなの??
って気分で一杯です。
私も普段この方法でやってるのですが、インスタンスが持つデータ量が
少しでも多くなると管理が煩雑になるんですよね。。。
それに、インスタンスフィールドにデータを持たせる方法だと、
コンパイルの段階でエラーに気づかないんですよねぇ。
実行するまでそこのtypoに気づかないのですわ。
例えば、(例えいるのか?)

$c->{'name'}

でアクセスできるフィールドがあったとして、間違って

$c->{'neme'}

と、してしまったと。

でもこれはperl -cでもエラーが見つけられないし、
その行を実行するまで分からないんですよね。

まだ詳細には読んでませんが、Perl Best Practicesでもインスタンスフィールドにデータを持たせるのはどうなのみたいに書いてました。

Perl Best Practicesでは確か、(適当なのでご自分で確認して下さい)


package MyClass2;
use strict;
use warnings;
{
my $name;
my $job;
sub new {
my($class,$self)=(shift,{@_});
bless($self,$class);
$self;
}
sub set_name {
my $self = shift;
$name = shift;
}
sub get_name {
$name;
}
}
1;

こういう風にしてました。
なんとなく俺はこれに賛成ですね。

これを踏まえてプログラム組みたいですねぇ。

CLASSは__PACKAGE__へのエイリアスを行うモジュールです。
__PACKAGE__が好きなかたはそれでどうぞ。


参考)

http://naoya.dyndns.org/~naoya/mt/archives/000563.html