アクセサの作り方のまとめ

アクセサ(2) AUTOLOAD でアクセサ - ぱるも日記

アクセサの作成方法はいろいろあるけど自作するならAUTOLOADとか使わずに、

 package Hoge::Class;
 use strict;
 
 for my $method (qw/age name tel hoge/) {
     my $code = sub {
         my $self = shift;
         $self->{$method} = shift if @_;
         return $self->{$method};
     };
     no strict 'refs';
     *{$method} = $code;
 }

って感じでクロージャと型グロブで定義すればいいかと。

AUTOLOAD使うなら使うで、初回呼び出し時にメソッド定義してしまうのがセオリーなんで、
二度目以降はAUTOLOADが呼び出されなくなるから遅いという問題は解決するかと。

 sub AUTOLOAD {
     my ($self) = @_;
     my $func   = $AUTOLOAD;
     return if $func =~ /::DESTROY$/;
     
     my ($class,$method) = $func =~ /(.+)::(.+)$/;
     my $code   = sub {
         my $self = shift;
         $self->{$method} = shift if @_;
         return $self->{$method};
     };
     
     no strict 'refs';
     *{$func} = $code;
     goto &$code;
 }

また、アクセサ名の打ち間違いは事前に使用するアクセサ名テーブルを用意かな。

 our %ACCESSOR = map { $_ => 1 } qw (
     age
     name
     tel
     hoge
 );
 sub AUTOLOAD {
     my ($self) = @_;
     my $func   = $AUTOLOAD;
     return if $func =~ /::DESTROY$/;
     my ($class,$method) = $func =~ /(.+)::(.+)$/;
     
     die qq{Can't locate object method "$method" via package "$class"}
         unless $ACCESSOR{$method};
     
     my $code = sub {
         my $self = shift;
         $self->{$method} = shift if @_;
         return $self->{$method};
     };
     
     no strict 'refs';
     *{$func} = $code;
     goto &$code;
 }

あとUNIVERSAL::canに関してはUNIVERSAL::canAUTOLOADがCPANにあるのでそれで解決。

とまあアクセサ作成方法をここまで書いておきながら一番いいのはClass::Accessor(or Class::Accessor::Fast)使うこと。

 package Hoge::Class;
 use base qw( Class::Accessor::Fast );
 __PACKAGE__->mk_accessors(qw/age name tel hoge/);

ただ僕個人的にはClass::Data::Accessorの方が好きなんでそっち使ってるけどね。