Entering Passive Mode

カテゴリ 'Perl' の記事
< 1 2 3 4 5 6... >

Carp 対策

プロパティによる Carp への影響を考えてみよう。
まずは、croak のメッセージの仕組みを調べるために、
コールスタックをトレースさせてみよう。

Carp モジュールに 'verbose' 引数を渡して取り込んだ場合、
croak が自動的にバックトレースつきで出力される。
なので、EmployeeTest.pl に、以下の行を加えておこう。

    use Carp 'verbose';

さて、$jack->set_salary(100000); の場合どうなるか。

property.pm を使ってみる

さて、property を使って、Employee.pm を作ってみよう。
基本的には他のモジュールを取り込むのと同じ要領だ。

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

package Employee;

use v5.6.1;
use strict;
use warnings;
use Carp;

モジュールの実装

では、property モジュールに実装を作っていこう。

まずは、use の呼び出しの規約を考える。
プロパティの作成に必要なのは、
名前、setter メソッド, getter メソッドの三つ。
それをハッシュで渡すようにしよう。

use property 'name' => 'salary',
        'get' => \&get_salary,
        'set' => \&set_salary;

シンボリックリファレンス

昨日の考察により、通常の手段によって、
文字列で受け取ったパッケージのシンボルテーブルに
新しくシンボルを追加することは難しいことが判明した。

しかし方法がないわけではない。
Perl には、特別なモジュールの作成を助けてくれる、
シンボリックリファレンスというものがあるのだ。

シンボリックリファレンスを使えば、
シンボルテーブルに存在するあらゆる値を、
「文字列」によって示す名前を使って参照することができる。
百聞は一見にしかず。例を挙げて試してみよう。

シンボルテーブルへの項目追加

文字列として与えられたパッケージに対して、
動的にメソッドを登録には、もう一つ壁がある

汎用化するため、プロパティを登録するパッケージは、
caller 関数で得られる「名前」となる。
「名前」は文字列のデータなので、
文字列を元にパッケージを探して、
それにメソッドを追加する必要がある。

自身のパッケージ(カレントパッケージ)の場合、
以下のようにコードを登録していた。

モジュール化

昨日は、型グロブ構文により、
自らのパッケージの内容を修正したが、
通常、そのようなことを行なう必要はあまりない。
それらは、通常通り直接定義したほうが見やすいからだ。

では、どのようなときに使うかというと、
自分ではなく、別のパッケージ内部を編集する場合だ。

例えば、Employee で行なっていたプロパティ作成は、
Employee クラス自身で実装しなくとも、
動的にサブルーチンが作れる機能を利用して、
別のモジュールから作成してもいいわけだ。

メソッドの動的登録

シンボルテーブルは、パッケージ内部を参照するだけでなく、
それを編集することで、パッケージに動的に
サブルーチンや変数などを登録することができる。

グロブの変数各種を参照する場合は、
データ型に応じたデリファレンスをしたが、
グロブに変数各種を格納する場合は、
グロブ自身に、変数のリファレンスを代入する。

my $ver = '0.06';
*Version = \$ver;

型グロブ

シンボルテーブルの中身をダンプしてみると、
そこにはメソッドや変数名が登録されていた。
しかし、全てのシンボルに * 文字が含まれている。
* がついているということは、型グロブであると言うことだ。

'salary' => *Employee::salary

Perl の識別子は、データ型ごとに名前空間を持つ。
なので、$value、@value、%value、&value、value は、
それぞれ異なる識別子として共存することができる。
通常は、先頭につく記号などでそれらを区別する。

シンボルテーブル

C# や Java には、リフレクションと呼ばれる機能がある。
プログラムからクラスのメンバの情報を得ることができ、
文字列で名前を指定してメソッドを呼ぶなどの能力をもつ。
Perl にも制限つきだが、同じような機能がある。

Perl のクラスはパッケージとして定義されるが、
パッケージにはシンボルテーブルと呼ばれる情報がある。
シンボルテーブルには、パッケージ内のサブルーチンや、
our で定義したパッケージ変数などが記録されている。

Perl シンボルテーブルは、実はただの連想配列である。
シンボルテーブルは、通常の変数と違い、
パッケージ名にコロンを 2 つつけた特別な名前を持つ。

複数のプロパティ

昨日書いた lvalue ルーチンを見てみよう。

sub salary : lvalue {
    my $this = $_[0];
    tie(my $reflector, 'Employee::Reflector',
            $this, \&get_salary, \&set_salary);
    $reflector;
}

検証は get_salary, set_salary で行っているので
lvalue ルーチン自体はかなりすっきりした。
では、同じようなプロパティを追加してみよう。
「部署」プロパティだ。

< 1 2 3 4 5 6... >
このページのトップへ戻る
© 2008 Project Loafer/Project Fireball and all blog writers. Powered by Nucleus CMS