tieってなんぞ

久しぶりにPerlにさわって見た。でだ、残念な事に全て忘れていたよ。と言うわけで忘れないようにメモしておく。

tieとは、

「オブジェクトではない、perlの組み込みデータタイプを裏でオブジェクト化する仕組み」
by 弾<参照>

の事だ。上記一文でもやもやしていたのが一気に晴れたよ。なるほど!と思った。今までtieを見たことはあったが実際の業務で必要だったかと言うと、そういった事はなくtieを知らなくても支障はなかった。tieってPerl4でオブジェクト指向っぽくコーディングしたい場合に役立つ機能だよね。Perl5ではなんちゃってオブジェクト指向の実装ができるから必要ないと思うんだが、知っておくことは必要だと思う。

use strict;
use warnings;
{
  package Foo;
  sub TIESCALAR {
    my $class = shift;
    my $self = {};
    bless $self, $class;
  }
  sub FETCH {
    print "fetch\n";
  }
  sub STORE {
    print "store\n";
  }
  sub DESTROY {
    print "destroy\n";
  }
}

tie my $foo, 'Foo';
$foo = 1;
my $bar = $foo;
exit;

で実行結果は、

tiescalar
store
fetch
destroy

面白くもなんともないね。

TIESCALARってのがtieで変数とパッケージを結びつけた際、一番最初に実行されるところ。コンストラクタと解釈してもいいと思う。次にFETCHだけど、FETCHはtieで結びつけた変数に対してアクセスしたときに呼ばれる。でSTOREは、その変数を他の変数等にストアした際に呼ばれ、DESTOROYは必要なくなったときに呼ばれる。

あと、TIEはSCALARだけじゃなく、ARRAY、HASH等と結びつける事ができ、それらはSCALARと比べたら多少複雑になる。実装しなければならない専用のメソッド(FETCHやSTORE等)が増える。とは言え基本的な考え方は変わらない。

で、tieをいろいろ調べてたんだが、tieって微妙だよね。例えば実装できるメソッドが既に決まっているって事でしょ。FETCHやSTORE等々、それら以外を実装したいと思えばどうしたらよいの。$varという変数に対して、新規にメソッドを追加したいのよ。

use strict;
use warnings;
{
  package Bar;
  sub TIESCALAR {
    ...
  }
  sub FETCH {
    ...
  }
  sub STORE {
    ...
  }
  sub DESTROY {
    ...
  }
  sub COUNT {
    my $self = shift;
    my $scalar = shift;
    return length($scalar);
  }
}

tie my $bar, 'Bar';
$bar = 9000;
print $bar->COUNT;  # 4 と出力される

とかだったら面白いよね。新しいメソッドを追加できたら、その動作をいろいろと変更できたら使いやすいと思うんだが、残念ながらできそうにないね。まあオブジェクト指向って考え方が後付された言語だから仕方ないかもって素直にblessやMoose使ってやれってことですね。わかりました。

でも、知っておくことは必要だと思った今日この頃です。では。