コンストラクタの遅延

ふと思いついて、CPAN検索したらいくつか既存モジュールあったけど、 英語読むのがめんどくさくてソースも長くて読むのがめんどくさかったので、 試しもせずに車輪の再発明をしてみました。

要はYet Another な Object::Realize::LaterClass::LazyObject です。

コンストラクタのコストが高いオブジェクトってありますよね、それらに対して、 使うかどうか分からないけど、一応newしておきたい。 アプリの初期化時にnewしたいけど、初期化でもたつきたくないので、実際に使う時までコンストラクタを遅延したい。 なんていう時に使います。

使い方は簡単

use Class::Lazy;
my $foo = YourHeavyClass->lazy::new(@args);

これだけ。つまりコンストラクタメソッドの前に lazy:: をつけるだけです。

あとは、この $foo に対してメソッドを呼び出した時点でフックされてコンストラクタ実行され、 その返値に対してメソッドが実行されます。 それ以降は $foo自体がすでにきちんと初期化されたオブジェクト(コンストラクタの返値)になっているので、 通常通りの動作をします。

package Class::Lazy;

use strict;
use warnings;
our $VERSION = '0.01';

sub AUTOLOAD {
    if(@{$_[0]} > 1) {
        my($caller, $constructor, $class, @args) = @{$_[0]};
        my $thing = $class->$constructor(@args)
            or die qq{Can't construct "$class" object with "$constructor"}
                . qq{at $caller->[1] line $caller->[2].\n};
        @{$_[0]} = $thing;
    }
    $_[0] = $_[0][0]; # realize it!

    our $AUTOLOAD =~ s/^.*:://o;
    my $method = $_[0]->can($AUTOLOAD);
    goto $method if $method;

    # method not found!
    shift->$AUTOLOAD(@_); # die?
}

# Override UNIVERSAL methods.
sub isa { $_[0][2]->isa($_[1]) };
sub can { $_[0][2]->can($_[1]) };

# Do not have to AUTOLOAD this.
sub DESTROY { undef; }

###########################################################################
package lazy;

sub AUTOLOAD {
    my $constructor = substr(our($AUTOLOAD), 6); # 6 == length('lazy::')
    bless [[caller()], $constructor, @_], 'Class::Lazy';
}

__END__

一度初期化されるまで、ref()の値が本来のものと違うとか、 overload されたオブジェクトでoverloadが有効にならないとか、 いろいろ制限はありますが、素直なメソッドによるオブジェクト操作だけなら有用なんではないかと思います。

2007/07/27追記

オーバーロードに対応して、もうちょっときちんとしたものをTracのプロジェクトページ に置きました。

カテゴリ

トラックバック(0)

このブログ記事を参照しているブログ一覧: コンストラクタの遅延

このブログ記事に対するトラックバックURL: http://www.fs-output.com/rintaro/mt/mt-tb.cgi/19

コメントする

(初めてコメントする場合、承認されるまではコメントが表示されない場合があります。)

このブログ記事について

このページは、Rintaroが2007年7月20日 16:51に書いたブログ記事です。

ひとつ前のブログ記事は「Object? HASH reference? - メソッドと tied ハッシュ 両方のインターフェイスを持つオブジェクト」です。

次のブログ記事は「Perlモジュールは__PACKAGE__を返すべきだ!」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

Powered by Movable Type 4.0rc4