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な必要ってなんにもなくなってますし。
二度目の…のは知っていますが関連一度読み返しておきます><(今回使ってないのは半分ネタの使い捨てくらいだったので)