Unless you really know what you are doing.
antipop2.0: Perl で楽々アクセサ作成について考えてみたhio (September 9, 2005 10:12 PM)
ちょっと変なコトしてみました. (perl 5.8.3以降じゃないとSEGVするみたいです)
http://fleur.hio.jp/~hio/accessor.pl
kentaro (September 10, 2005 12:28 AM)
どうもどうもです! UNIVERSAL::AUTOLOAD をいじるコードとか、初めてみましたよ! なるほどそういうやり方もあるんですねぇ。奥が深い……。
感心している場合じゃないって!
&UNIVERSAL::AUTOLOADを定義するというのは、あまりに推奨できない方法です。&AUTOLOADを定義せず、かつ@ISAの中にあるパッケージのいずれも定義していないパッケージでは全てこれが使われてしまい、あまりに危険です。未定義のmethodをきちんとエラーとしてPerlに捕まえて欲しい時にもなんでもありになっちゃいます。このレベルの「邪道」は、本当にわかっていないと危なすぎる、筋弛緩剤クラスの危険度です。少なくともno strict;より危険。
こういうModuleが、例えば複数人で開発しているmod_perlベースのサイトに突っ込まれたときのことを考えても見て下さい。
#「救急病棟」レベル10の人がむやみにUNIVERESAL::に頼っちゃ行けませんなあ
同じ事をしたいのであれば、継承を使えばいいだけの話です。
package Class::Accessor::Nested;
use Carp;
sub AUTOLOAD {
my $this = shift;
my $name = our $AUTOLOAD;
$name =~ s/.*:://o;
$name eq 'DESTROY' and return;
ref($this) && $name or croak "Undefined subroutine $name called";
@_ and $this->{$name} = shift;
ref $this->{$name} eq 'HASH' and bless $this->{$name}, ref($this);
$this->{$name};
}
1;
とでも定義しておき、
package MyData;
use base 'Class::Accessor::Nested';
sub new{
my $pkg = shift;
my $data = shift || {};
bless $data, $pkg;
}
として使えば良い。Testしたらちゃんと動きましたよ。
さらに、以下のようにすれば、二度目の呼び出し以降は&AUTOLOADが呼び出されることすらありません。
sub AUTOLOAD {
my $this = shift;
my $name = our $AUTOLOAD;
$name =~ s/.*:://o;
$name eq 'DESTROY' and return;
ref($this) && $name or croak "Undefined subroutine $name called";
{
no strict 'refs';
*$name = sub {
# warn "$name predefined";
my $self = shift;
@_ and $self->{$name} = shift;
ref $self->{$name} eq 'HASH' and bless $self->{$name}, ref($self);
$self->{$name};
};
}
# warn "$name first called";
@_ and $this->{$name} = shift;
ref $this->{$name} eq 'HASH' and bless $this->{$name}, ref($this);
$this->{$name};
}
実はこの辺の話題はラクダ本にもきちんと出てきます。車輪や毒を再発明する前にきちんと目をとおしておきましょう。
Dan the Just Another AUTOLOAD Hacker
あぅ〜全然考えてなかったですごめんなさい;_;
もうちょっとWebの広さを考えないとですね;_;
ひとまずソースは見れないようにしておきました.
子ノードでもアクセスできるように→どこでもアクセスといったらUNIVERSAL?→でもblessされてなきゃだめよね…→うにゅ、やっぱりだめっぽい→とりあえずbless〜→うごいたうごいた。ってかんじだったのですけれど、blessする時点で継承ツリーつかうからUNIVERSALな必要ってなんにもなくなってますし。
二度目の…のは知っていますが関連一度読み返しておきます><(今回使ってないのは半分ネタの使い捨てくらいだったので)