このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。
Java や C# では、Object というルートクラスがある。
あらゆるクラスは暗黙的に Object から派生している。
Perl にも同様、暗黙的ルートとなるクラスがある。
それは、UNIVERSAL クラスと呼ばれる。
UNIVERSAL は Perl が特殊扱いするクラスであり、
@ISA を明示しなくても継承されているとみなされる。
UNIVERSAL には、isa, can と呼ばれる関数がある。
これらはオブジェクトの実装を確認するために使用できる。
isa, can はメソッドとしても機能し、
あらゆるオブジェクトにはこれらが継承されている。
isa はオブジェクトが特定のクラスかどうか確認できる。
Java の instanceof や C++ の dynamic_cast とほぼ同じだ。
my $boolean = $object->isa('ClassName');
can はオブジェクトに対して、特定のメソッドを
呼び出せるかどうかどうか確認できる。
これは非常に面白い機能である。
my $code_ref = $object->can('method_name');
もしオブジェクトに対して、指定した名前のメソッドでの
呼び出しが可能であれば、メソッドを実装している
パッケージのメソッドのコードリファレンスが返る。
不可能ならば、undef が返るのだ。
このメソッドが返却するコードリファレンスは、
最終的にメソッドを実装している実体であるため、
メソッドがオーバーライドされていたとしても、
実際にメソッドを呼び出した際に実行されるコードを示す。
なので、このコードリファレンスを使って、
オブジェクトのメソッドを呼び出しても問題ないのだ。
では、setter に対応する STORE を書き換えてみよう。
sub STORE {
my ($this, $value) = @_;
my $object = $this->{'object'};
my $method = $this->{'set'};
my $code = $object->can($method);
# setter が呼び出せない場合は読み取り専用。
croak "Can't set value to this property."
if not defined $code;
$object->$code($value);
}