2006 年 4 月 11 日 23 時 56 分

スカラの tie


このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。


スカラ変数は、値を一つ格納するだけしかできないので、
スカラ用の tie オブジェクトは非常にシンプルである。
これらが実装する必要があるのは、以下のメソッドだけだ。

TIESCALAR, STORE, FETCH

TIESCALAR は tie から呼ばれるクラスのコンストラクタで、
STORE は、スカラに値を代入する際に、
FETCH は、スカラから値を取得する際に呼び出される。

では、Employee クラスを拡張してみよう。

========== Employee.pm ==========

package Employee;

use v5.6.1;
use strict;
use warnings;

BEGIN {
    our $Version = '0.04';
}

sub new {
    my ($package, %identity) = @_;
    $package = (ref $package or $package or __PACKAGE__);
    bless(\%identity, $package);
}

sub name {
    $_[0]->{'name'};
}

sub gender {
    $_[0]->{'gender'};
}

sub weight {
    $_[0]->{'weight'};
}

sub salary : lvalue {
    my $this = $_[0];
    tie(my $magic, 'Employee::MagicScalar', \$this->{'salary'});
    $magic;
}

package Employee::MagicScalar;

use v5.6.0;
use strict;
use warnings;

sub TIESCALAR {
    my ($package, $ref_scalar) = @_;
    $package = (ref $package or $package or __PACKAGE__);
    bless($ref_scalar, $package);
}

sub FETCH {
    my $this = $_[0];
    print "FETCH\n";
    $$this;
}

sub STORE {
    my ($this, $value) = @_;
    print "STORE\n";
    $$this = $value;
}

1;

========== end of Employee.pm ==========

Employee::MagicScalar は特定のスカラへのプロキシとなり、
代入と取得操作を監視している。
salary サブルーチンは、通常のスカラではなく、
Employee::MagicScalar を tie されたスカラを返す。

これにより、salary の外であっても、
代入や取得を追跡できる状態となる。

テスト用のスクリプトは前とほとんど同じだ。
グローバルの $\ を使うのをやめただけ。

========== EmployeeTest.pl ==========

#!/usr/local/bin/perl

use strict;
use warnings;
use lib '.';
use Employee;

my $jack = Employee->new(
    'name'  => 'Jack',
    'gender' => 'male',
    'salary' => 160000,
    'weight' => '65kg',
);

print "Salary: ", $jack->salary, "\n";

$jack->salary = 200000;

print "Salary: ", $jack->salary, "\n";

========== end of EmployeeTest.pl ==========

実行してみよう。

$ perl ./EmployeeTest.pl
FETCH
Salary: 160000
STORE
FETCH
Salary: 200000

値の取得時に FETCH が、
設定時に STORE が呼び出されていることが分かる。



Copyright (c) 1994-2007 Project Loafer. All rights reserved.