From: Takeshi Horinouchi Date: 2003-08-11T18:25:47+09:00 Subject: [ruby-list:38077] Re: module extendable? 堀之内です。 > なかだです。 ご教示ありがとうございます。 > > モジュールをネストして module_function を継承(のようなことを) > > することはできるでしょうか。具体的には、モジュールに入れたアルゴ > > リズム(メソッド群)を取り替えやすくするため、以下のようなことを > > したいのですが、うまくいきません。使用しているのは ruby 1.6.8 で > > す。同様のことをするのに別の方法があるよとか、1.6 ではだめだけど > > 1.8 ならできるといった情報でも結構です。(まだしばらく1.6は切り > > 捨てたくないので困りはしますが。。。) > > module_functionは、インスタンスメソッドをメタクラスにコピーして > 元のインスタンスメソッドはprivateにします。 > > > module Foo > > module_function > > def hi; "hi"; end > > def there; "there"; end > > end > > module Bar > > module_function > > extend Foo > > def hi; 'HI'; end > > end > > ここでextendは、Barのメタクラス(カッコをつけて(Bar)と表記)にモ > ジュールFooをincludeするので、(Bar)にインスタンスメソッドhiと > thereが追加されます。つまり、Bar自身の特異メソッドとして追加さ > れるのはprivateであるFoo#hiとFoo#thereであって、publicであるク > ラスメソッドFoo.hiやFoo.thereではありません。 > > ということで、extendしてからpublic_class_method :thereとすれば > アクセスできるようになります。 ちゃんと理解できてませんが、module_function にするものは、もとは public_class_method でないといけないんですね。確かにマニュアルを 見ると、module_function は、プライベートかつモジュール関数にする と書いてあります。ともかく、メールに書いたソースの extend の後に public_class_method :there を加えるだけで、モジュール関数として使えることを確認しました。 ありがとうございました。 > > なお、module Bar において extend でなく include にしてもだめです。 > > > > /.../nested_modules2.rb:18:in `there': undefined method `there' > > for Bar:Module (NameError) > > from /.../nested_modules2.rb:26 > > スーパークラスのクラスメソッドが継承されるように、includeされた > モジュールのクラスメソッドも継承されるべき、ということでしょう > か。 理解できてないので、「べき」かどうかは全くわかりません。 class に include する場合にはモジュール内に別のモジュールを include できるので、類推でやってみたけど出来なかったまでです。 ただ、 public_class_method :there とするよりもわかりやすい方法があってもいい気はします。 (あるいはこの手法をマニュアルに載せるか...。 もし、これが想定されてない「裏技」ならば、将来使えなくなる かもと、少し不安に思います。)