Perl でオブジェクト指向 C++風 その2 クラス変数
先の記事で「パッケージ」でインポートした関数などを、「クラス」で使う方法を書いた。本稿では同方法で、「クラス変数」をどのように実現するか例示する。
■ |
方法1:$class->get_template()->{cvar} を使う。
|
{ package Main::_C1; use base qw(Main::_Simple); our $classvar_1 = 0; # クラス変数の実体、このままでは「継承」されない。 __PACKAGE__->extend_template ( member_1 => 1.0, # ここに member_1 の説明を書こう! cvar_1 => \$classvar_1, # クラス変数の登録 ); sub method_2 { # クラス変数を print するだけ。 my $self = shift; print ${ref($self)->get_template()->{cvar_1}} . "\n"; } } { package Main::_C2; use base qw(Main::_C1); } MAIN: { my $c1 = Main::_C1->new(); my $c2 = Main::_C2->new(); $c1->method_2(); # 0 と表示。 $c2->method_2(); # 0 と表示。 ${Main::_C1->get_template()->{cvar_1}} = 1; $c2->method_2(); # C1 を変えたのに c2 が 1 と表示。 ${Main::_C2->get_template()->{cvar_1}} = 2; $c1->method_2(); # C2 を変えたのに c1 が 2 と表示。 }
実行結果はなんの衒 いもなく以下のようになる。
$ perl example_oo_c1.pl 0 0 1 2
extend_template は dclone していないため、このようなことができる。
もちろん、$c1 を new するときは、dclone が呼ばれているため、 $c1->{cvar_1} は Main::_C2->get_template()->{cvar_1} とは別の(スカラ変数の)参照を持ってしまい、その分、メモリが無駄になる。
肯定的にとらえれば、$c1 が生成されたときのクラスの状況は自動的に転写されるため、当初との違いが必ず比較されうるというプレッシャーをクラスの管理人(だいたい自分)に与えることができるといえよう。
■ |
方法2:コンストラクタを使う。
|
Main::_Simple までは先の記事とほぼ同じで、今度はコンストラクタを使って、「クラス変数」の格納場所を一種のオブジェクトとみなし、常にコンストラクタで登録していく。(動くソースはexample_oo_c2.pl。)
{ package Main::_C1; use base qw(Main::_Simple); our $classvar_1 = 0; # クラス変数の実体、このままでは「継承」されない。 __PACKAGE__->extend_template ( member_1 => 1.0, # ここに member_1 の説明を書こう! cvar_1 => undef, # ここにはクラス変数の参照が入る。 ); sub method_2 { # クラス変数を print するだけ。 my $self = shift; print ${$self->{cvar_1}} . "\n"; } sub new { my $class = shift; my $obj = $class->SUPER::new(@_); $obj->{cvar_1} = \$classvar_1; return $obj; } } { package Main::_C2; use base qw(Main::_C1); } MAIN: { my $c1 = Main::_C1->new(); my $c2 = Main::_C2->new(); $c1->method_2(); # 0 と表示。 $c2->method_2(); # 0 と表示。 ${$c1->{cvar_1}} = 1; $c2->method_2(); # C1 を変えたのに c2 が 1 と表示。 ${$c2->{cvar_1}} = 2; $c1->method_2(); # C2 を変えたのに c1 が 2 と表示。 }
実行結果は上の例と同じである。
ただ、この方法を使うなら、わざわざ「クラス変数」の参照にする必要はない。つまり、our $classvar_1 に直接、オブジェクトを代入しておき、それをコンストラクタで常に新しいオブジェクトに登録するようにすればいいのである。
「クラス変数」にオブジェクトを入れたくなったら、その前に、少し考えて欲しい。コンストラクタを使うなら、あるオブジェクトを、継承された全オブジェクトで共有するのは簡単なのだから。
逆に考えれば、「クラス変数」は、文字列や数値を「環境変数」的に利用したい場合にのみ使うに留めるべきだと、私は、思う。
■ |
関連
|
更新: | 2011-01-06 |
初公開: | 2011年01月06日 13:13:56 |
最新版: | 2011年01月06日 22:27:12 |
2011-01-06 13:13:55 (JST) in Perl | 固定リンク | コメント (0) | トラックバック (1)
トラックバック
他サイトなどからこの記事に自薦された関連記事(トラックバック)の一覧です。
» JRF のソフトウェア Tips:Perl でオブジェクト指向 C++風 その2 クラス変数 (この記事)
» Perl でオブジェクト指向 C++風 その3 ローカル関数 from JRF のソフトウェア Tips
先の記事で「パッケージ」でインポートした関数などを、「クラス」で使う方法を書いたが、インポートした関数の他に、Main パッケージで定義した「ローカル関数」も「クラス」で使いたくなるのが当然である。(というより、それができないことにさっき気付いた。)本稿ではほぼソースだけだがその方法を示す。... 続きを読む
受信: 2011-01-07 22:45:05 (JST)
コメント