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);
}