Perlのオブジェクト指向とか。

Perlオブジェクト指向は面白いなあ。C++なんかのソレとは違う感じ。「要は、スコープがあって(package)、コンテキストによってアクセスできる関数を選択できて(bless)、継承が出来ればいいんでしょ(@ISA)?」みたいな考え方。C++/javaみたいに厳密なアクセス制御とかないし、コンストラクタも明示的に呼ばないと駄目だけど、考えたことをつらつら書くにはもってこいかも。まあ、try-catch構文が無いからエラーハンドリングが面倒な感じはする。


ところで先にも書いたとおり、継承は@ISAで行われている。@ISAはよく継承に利用される、と紹介されているが厳密にはパッケージにシンボルが見あたらないときに探しに行くパッケージの名前を示す特殊配列だ。これは、つまり「funcはカレントのレキシカルスコープにはありませんね。じゃあ@ISAを探して…ああ、SuperClassにfuncがあるからそっちを呼ぶか」というような感じになる。だがこれでは、funcの中ではSuperClassのレキシカルスコープが適用されてしまう。このような場合、SuperClassとSubClassそれぞれのpackageの中でmyで宣言している変数valueに対してアクセスできるのはSuperClass側になってしまう。つまり、C++でいえばprivateで同じ変数を宣言している状態ですね。


では、protectedに相当するものはないのか?


…うーん。
どうしてもやりたいのなら、newで返すハッシュの中に入れてあげて、$self->{member}ってやることかなあ。外から変更できちゃいますよね、突っ込みについてはPerlって元々そんな感じじゃん?と返すほかありませんが。(^_^;


ちなみに、memberが関数へのreferenceの場合はSuperClassからSubClassの関数を呼ぶことも可能みたい。これはC++では出来なさそう。C++では、関数へのポインタであっても型チェックがあって、スコープ名も書かないといけないみたいなんで…
まあ、できていいのかよという突っ込みはおいといて。
でもまあ、イベントドリブン的なクラスを定義するとき、SuperClass側でディスパッチャを書いておいて、SubClass側ではイベントと呼び出すメソッドのテーブルを作っておく…なんてことができるから便利なのかな。←想像
# デザインパターンを良く読め!と怒られそうだ。

package SuperClass;

my $s= "This is SuperClass!";

sub func {
	print $s,"\n";
}

sub original {
	print "This is original!\n";
}

sub func_caller {
	my $self= shift;
	&{$self->{call}};
}


sub new {
	my $pkg= shift;
	my $hash= {
		"call"=> \&original,
	};
	bless $hash, $pkg;
}
1;

package SubClass;
import SuperClass;
@ISA= qw(SuperClass);

my $s= "This is SubClass!";

sub replaced {
	print "This is replaced!\n";
}

sub new {
	my $pkg= shift;
	my $hash= SuperClass->new;
	$hash->{"call"}=  \&replaced;
	bless $hash;
}

package main;
use Data::Dumper;
import SuperClass;
import SubClass;

my $a= SuperClass->new;
print "**SuperClass Object**\n";
$a->func;
$a->func_caller;


my $b= SubClass->new;
print "**SubClass Object\n";
$b->func;			# <-- レキシカルスコープはSuperClassになる。
$b->func_caller;	# <-- SuperClassの関数だがサブクラスの関数を呼べる。


ところで、Perlでは純粋仮想関数が定義できないからCPANにソレ用のモジュールがあるという話だけど、SuperClass側でdie "func is pure virtual function."とかやればオッケーな気もしますがいかがか?