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."とかやればオッケーな気もしますがいかがか?