最近の記事
- 9/1 - 将棋始めました
- 5/16 - サーバー引っ越し
- 4/24 - 優先順位
- 3/17 - vbNullString と 空文字列 ""
- 3/15 - InputBox 関数の戻り値
- 3/13 - 紙と Excel と VBA
- 3/9 - 未だに Visual Basic 6
- 11/14 - ぼて閉鎖
- 11/9 - 関数オブジェクトの呼び出し
- 9/7 - メソッドとしての関数オブジェクト
Entering Passive Mode
プロパティによる Carp への影響を考えてみよう。
まずは、croak のメッセージの仕組みを調べるために、
コールスタックをトレースさせてみよう。
Carp モジュールに 'verbose' 引数を渡して取り込んだ場合、
croak が自動的にバックトレースつきで出力される。
なので、EmployeeTest.pl に、以下の行を加えておこう。
use Carp 'verbose';
さて、$jack->set_salary(100000); の場合どうなるか。
さて、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 ルーチン自体はかなりすっきりした。
では、同じようなプロパティを追加してみよう。
「部署」プロパティだ。