このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。
そこそこ洗練されてきた property モジュールだが、
まだまだ課題点はある。
問題の一つは、登録時に setter/getter の
コードリファレンスを指定していることだ。
Perl におけるコードリファレンスは、
関数を指すリファレンスであり、
メソッドを指すリファレンスとはならない。
関数とメソッドに、構文上の違いはないが、
メソッドのリファレンスを取ると、
それはメソッドとしての意味を失い、
ただの関数のリファレンスとして扱われる。
こういうと難しいかもしれないので、今回も例を挙げよう。
use strict;
use warnings;
package Base;
sub new {
my $package = shift;
my $value = shift;
bless({'value' => $value}, $package);
}
sub get_value {
my $object = shift;
$object->{'value'};
}
sub mul10 {
10 * shift;
}
package Derived;
our @ISA = ('Base');
package main;
my $obj = Derived->new(3000);
print "Value: ", $obj->get_value, "\n";
print "x10: ", Base::mul10(20), "\n";
Base は new と get_value, mul10 を持つ簡単なクラスだ。
new はクラスメソッドであり、
get_value はインスタンスメソッド、
mul10 は関数である。
それぞれどこが違うかみてみよう。
メソッドへの呼び出しには、アロー演算子が使われる。
メソッドの特徴は、継承を考慮するということだ。
クラスメソッドは、パッケージ名->メソッドの形だ。
Derived->new は、Derived の new メソッドを探す。
見当たらない場合、@ISA を参照して親クラスから探す。
最終的に見つかったメソッドの第一引数に、
'Derived' という文字列を渡して呼び出される。
インスタンスメソッドは、インスタンス->メソッドの形だ。
$object->get_value は、$object のパッケージから
get_value メソッドを探す。
$object は bless されているため、
自分のパッケージ名を知っているのだ。
見当たらない場合、@ISA を参照して親クラスから探す。
最終的に見つかったメソッドの第一引数に、
$object 自身を渡して呼び出される。
上記では、Derived 自身にはメソッドが定義されていないが、
Derived は Base を継承していることを @ISA で示しており、
上の 2 つのメソッドは、Derived からも呼び出せるのだ。
関数は、パッケージ名::関数名 として呼び出される。
mul10 は、Base パッケージに定義されているので、
Base::mul10 と限定名を使って呼び出しているのだ。
関数は、継承とは関係ないため、
Derived::mul10 とすれば見つからないというエラーとなる。
このように、サブルーチンは、呼び出し方によって、
メソッドとなったり、関数となったりするのだ。
さて、コードリファレンスは、
サブルーチンへの参照でしかない。
そのため、メソッドのリファレンスを取ったとしても、
それはただの関数のリファレンスになってしまうのだ、
そこには、継承の概念はない。
明日は、これがどのような問題となるか考えてみよう。