Entering Passive Mode

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

取りあえず完成

さて、今日で完成としよう。

必要な機能は、引数無しで指定した場合、
自動的にシンボルテーブルのメソッドを調べることだ。

ただ、モジュールが use された直後ではまずい。
use は、暗黙的に BEGIN ブロックで実行されるため、
定義されているメソッドが読み込まれる前に実行される。

そのため import 内で対象のシンボルテーブルを検索しても、
シンボルテーブルにはまだメソッドが定義されていない。
対策として、import ではパッケージ名だけ記憶しておき、
シンボルテーブルの検索は後で行えばよい。

シンボルの列挙

では、シンボルテーブルからコードを検索してみよう。
例えば、Carp のシンボルテーブルを調べてみる。

    use Carp;

まずはシンボルテーブルを取得する。

    my $package = 'Carp';
    no strict 'refs';
    my $symbol_table = \%{"${package}::"};
    use strict 'refs';

メソッドの存在確認

最後に、新しくモジュールを起こす場合に
便利と思われる機能を考えてみよう。

現行の property モジュールの仕様であれば、
setter/getter の多いモジュールの場合、
それらをプロパティ化するために、
いくつも指定しなければならない。

use property 'name';
use property 'gender';
use property 'weight';
use property 'salary';

ここまでの整理

ここまで幾つかの考察をしてきた。
property モジュール全体を書き直してみよう。

プロパティ名、転送先 getter/setter メソッド名は、
継承上の問題により、共に文字列で指定し、
動的に処理する方が相応しいことが判明した。

property モジュールの引数はハッシュリファレンスだが、
そのパラメータは全て文字列で渡されることになる。
例えばプロパティが、'salary' の場合、
getter/setter は、'set_salary', 'get_salary' となる。

UNIVERSAL クラス

Java や C# では、Object というルートクラスがある。
あらゆるクラスは暗黙的に Object から派生している。
Perl にも同様、暗黙的ルートとなるクラスがある。
それは、UNIVERSAL クラスと呼ばれる。

UNIVERSAL は Perl が特殊扱いするクラスであり、
@ISA を明示しなくても継承されているとみなされる。

UNIVERSAL には、isa, can と呼ばれる関数がある。
これらはオブジェクトの実装を確認するために使用できる。
isa, can はメソッドとしても機能し、
あらゆるオブジェクトにはこれらが継承されている。

読み取り・書き込み専用

さて、今までは読み書き両用でみてきたが、
現実には、読み取り専用のプロパティや、
書き込み専用のプロパティもある。

property のインタフェースは、
プロパティ名、getter、setter の名前を渡すことだが、
読み取り専用や書き込み専用の場合どうするか。

1. getter、setter として、undef を渡せるようにする。

getter が undef の場合、読み取りはできない、
setter が undef の場合、書き込みはできない。
そのように実装することは可能だ。
property 側は undef かメソッド名か調べ、
undef であれば、croak すればいいというわけだ。

継承に対応させる

property.pm を動的呼び出しに対応させるには、
インタフェースを変更しなければならない。

従来はコードリファレンスを受け取っていたが、
新しい考え方では、メソッド名を渡すことになる。

幸い、リリース段階でないので、
今後のことを考えてインタフェースを変更しよう。

引数をハッシュで渡すのは効率が悪いので、
ハッシュリファレンスを使うことにする。

メソッドの動的呼び出し

昨日の考察により、コードリファレンスを使って、
オブジェクトのメソッドを呼ぶことは、
継承上の問題を生ずるため使えないことが判明した。

では、メソッドを動的に呼び出すにはどうすれば良いか。
Perl には、メソッドへのリファレンスは存在しないため、
事前に分かっていないメソッドを引き渡すには、
文字列によるメソッド名の指定しかない。

では名前を使ってメソッドを呼ぶにはどうすればいいか。
Perl はこれまた意外な答えを持っている。

継承とコードリファレンス

property モジュールはコードリファレンスを使って、
該当パッケージのメソッドを関数のように呼び出す。
これは、継承の問題と関連し、以下の問題を生じる。

1. 継承したメソッドをプロパティ化できない

あるクラスを継承したクラスを作る場合、
祖先クラスに get_XXX/set_XXX のメソッドがあると、
継承したクラスはそれらを利用できる。

しかし、それらをオーバーライドしない限り、
メソッドの実体は祖先クラスにあり、
継承クラスにはメソッドの定義自体が存在しない。

関数とメソッド

そこそこ洗練されてきた property モジュールだが、
まだまだ課題点はある。

問題の一つは、登録時に setter/getter の
コードリファレンスを指定していることだ。

Perl におけるコードリファレンスは、
関数を指すリファレンスであり、
メソッドを指すリファレンスとはならない。

関数とメソッドに、構文上の違いはないが、
メソッドのリファレンスを取ると、
それはメソッドとしての意味を失い、
ただの関数のリファレンスとして扱われる。

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