[kansaipm] Re: Privateなサブルーチン

Yasushi Nakajima sey at jkc.co.jp
Thu Feb 7 18:40:35 CST 2002


mishima> Class->sub() と呼ばれた場合には、1個目の引数にクラス(パッケージ)の
mishima> 名前が渡ってくるんじゃなかったでしょうか。
mishima> Class::sub() だと引数は見たまんま(この場合は引数無し)で、
mishima> $instance->sub() の場合には、1個目の引数に bless されたリファレンスが
mishima> 渡ってくるんですよね。
mishima> 
mishima> そういうので区別できないでしょうか。

 すみません。説明不足でしたね。Class->sub() と呼ばれた場合と、
Class::sub('Class') と呼ばれた場合、あるいは $obj->sub() と呼ばれた場合
と Class::sub($obj) と呼ばれた場合の区別を、サブルーチン側で付けられるか
という話です。

 つまり、メソッドとして呼ばれると第一引数にクラス名やオブジェクトが渡さ
れますが、その代わりに自分で第一引数にクラス名やオブジェクトを渡して普通
のサブルーチン呼び出しをしてもよいわけです。(この場合、継承の問題は別の
話です。)これは、Perlが過去との互換性を保ちながらオブジェクト指向を盛り
込むための実に巧みな仕組みといえますね。

 ところがこれが仇となる場合もあります。メソッドとして呼び出すことを想定
していないサブルーチンでも、メソッドとして呼び出せてしまい、その場合は第
一引数にいわば余分なものが挿入されてしまうのです。

 クラスを自分で書いた場合に、メソッドから呼び出して使う下請けのサブルー
チンを書くことがあると思います。その下請けサブルーチンが引数にオブジェク
トを必要とするなら、第一引数にオブジェクトを取るように書いておけば、普通
にサブルーチンとして呼ぶことも、メソッドとして呼ぶこともできます。

  package Class;
  sub _sitauke { my $obj = shift; … }
  sub method { 
    my $obj = shift; 
    _sitauke($obj,…); # OK
    $obj->_sitauke(…); # これもOK
  }

 特にサブクラスからもこの下請けを呼びたい場合は、このようにメソッドとし
ておくとよいわけですね。

 しかし、下請けサブルーチンがオブジェクトを必要としないケースもあります。
例えば、あるクラスのいろんなメソッドの中で、リストを先頭に日時を付加して
文字列化するという操作をおこなうとすると、次のような下請けサブルーチンを
用意することになるでしょう。

  package Class;
  sub _timestamped { scalar(localtime).": @_" }

 これを、$obj->_timestamped(…) と呼び出してしまうとおかしな結果になる
わけです。

 そこで、メソッドとして呼ばれることを想定していないサブルーチンをメソッ
ドとして呼ぶとエラーになるような仕組みを作れないだろうか。というのが、私
の問題意識な訳です。

 もちろんPerlのソース自体に手を加えてよいならいくらでも方法はあるのです
が、外付けのモジュールでこれができないかと考えているのです。その場合に、
呼ばれたサブルーチンの側でメソッドとして呼ばれたのかどうかを判別する方法
があれば、ほぼ問題解決に近づくのだけど…というお話しでした。

中島 靖




More information about the Kansai-pm mailing list