UNIVERSALクラス

自分用メモ。

Perlでblessされて作成されるオブジェクトは、すべてUNIVERSALクラスを継承するらしい。という話を聞きつつ、これまで特に用は無かったで放っておいたのだが、最近ちょっと気になって調べてみた。

perldoc UNIVERSAL

UNIVERSALクラスでいくつかのメソッドが定義されていて、他のクラスはすべてこれを継承するので、すべてのクラスでUNIVERSALクラスのメソッドが使用出来る。

isaメソッドは、指定したクラスを継承しているかどうかを調べる。canメソッドは、指定したメソッドのコードリファレンスを返す。VERSIONはpackage内の$VERSION変数の内容を返し、このとき引数があると、クラスの$VERSIONと比較してクラス側$VERSIONが小さいときにdieする。まぁ、やってみよう。

package Test;
use strict;
use base qw/ CGI Storable Template /;

$Test::VERSION = '1.0.0';

sub new {
	my $class = shift;
	bless { @_ }, $class;
}

sub method {
	my $self = shift;
	my $key = shift;
	my $value = shift;
	
	if( $value ){
		$self->{$key} = $value;
	}
	
	return $self->{$key} || "no key";
}

1;

こんな感じのモジュールを用意してみた。newはコンストラクタで、ハッシュリファレンスをセットするのみ。methodは自分自身のハッシュリファレンスにアクセスする。特に意味はない。まぁ、CGIとStorableとTemplateを継承するオブジェクトなんて実際には無かろうが、まぁ実験なんでいいや。

次にテストプログラム。test.plとした。

#!/usr/bin/perl
use strict;
use lib '/Users/a_aql/Desktop';
use Test;

my $test = Test->new(
	test1	=> 'foo',
	test2	=> 'bar'
	);

# 実行テスト
print "test?t: ".$test->method('test2')."?n?n";

# UNIVERSALクラスのメソッドを試す
print "isa(CGI)?t: ".$test->isa("CGI")."?n";
print "isa(DBI)?t: ".$test->isa("DBI")."?n";
print "can(method)?t: ".$test->can('method')."?n";
print "can(foo)?t: ".$test->can('foo')."?n?n";
print "VERSION?t: ".$test->VERSION."?n?n";

# canで得られたコードリファレンスを実行してみる
print "CODE REF?t: ".$test->can('method')->($test,'test1')."?n";

exit;

最初はひとまずTestクラスを実行してみる。次にUNIVERSALクラスのメソッドを試し、最後にcanで得られるコードリファレンスの実行を行ってみた。

実行結果は次の通り。

pico1:~/Desktop a_aql$ perl test.pl
test    : bar

isa(CGI)        : 1
isa(DBI)        : 
can(method)     : CODE(0x185c938)
can(foo)        : 

VERSION : 1.0.0

CODE REF        : foo

まぁ、予定通りの結果が得られている。

何に使うか…結構思いつくものもあるのだが、とりあえずそれは思案中なので置いておくことにするかな。とにかく、すべてのクラスで使えることが保証されている訳で、クラスのチェックの時に安心して使うことが出来そうだ。モジュールで$VERSIONをセットする理由を今回初めて知ったとかは内緒だ。