なかだです。

At Mon, 11 Aug 2003 18:25:47 +0900,
Takeshi Horinouchi wrote:
> > module_functionは、インスタンスメソッドをメタクラスにコピーして
> > 元のインスタンスメソッドはprivateにします。
> 
> ちゃんと理解できてませんが、module_function にするものは、もとは
> public_class_method でないといけないんですね。確かにマニュアルを
> 見ると、module_function は、プライベートかつモジュール関数にする
> と書いてあります。

もとはインスタンスメソッドとして定義されている必要があります。
publicである必要はありません。

> > > なお、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
> 
> とするよりもわかりやすい方法があってもいい気はします。
> (あるいはこの手法をマニュアルに載せるか...。
> もし、これが想定されてない「裏技」ならば、将来使えなくなる
> かもと、少し不安に思います。)

むしろ、Module#extendとModule#module_functionの動作からは当然の
帰結なので、不要になることはあっても動かなくなる可能性は低いと
思います。


Index: class.c =================================================================== RCS file: /cvs/ruby/src/ruby/class.c,v retrieving revision 1.76 diff -u -2 -p -r1.76 class.c --- class.c 6 Aug 2003 21:50:05 -0000 1.76 +++ class.c 12 Aug 2003 06:33:56 -0000 @@ -352,5 +352,5 @@ rb_include_module(klass, module) VALUE klass, module; { - VALUE p, c; + VALUE p, c, m; int changed = 0; @@ -367,10 +367,12 @@ rb_include_module(klass, module) } + again: OBJ_INFECT(klass, module); c = klass; - while (module) { + m = module; + while (m && m != klass) { int superclass_seen = Qfalse; - if (RCLASS(klass)->m_tbl == RCLASS(module)->m_tbl) + if (RCLASS(klass)->m_tbl == RCLASS(m)->m_tbl) rb_raise(rb_eArgError, "cyclic include detected"); /* ignore if the module included already in superclasses */ @@ -378,5 +380,5 @@ rb_include_module(klass, module) switch (BUILTIN_TYPE(p)) { case T_ICLASS: - if (RCLASS(p)->m_tbl == RCLASS(module)->m_tbl) { + if (RCLASS(p)->m_tbl == RCLASS(m)->m_tbl) { if (!superclass_seen) { c = p; /* move insertion point */ @@ -390,8 +392,13 @@ rb_include_module(klass, module) } } - c = RCLASS(c)->super = include_class_new(module, RCLASS(c)->super); + c = RCLASS(c)->super = include_class_new(m, RCLASS(c)->super); changed = 1; skip: - module = RCLASS(module)->super; + m = RCLASS(m)->super; + } + if (BUILTIN_TYPE(klass) != T_ICLASS && !FL_TEST(klass, FL_SINGLETON)) { + klass = RBASIC(klass)->klass; + module = RBASIC(module)->klass; + if (module) goto again; } if (changed) rb_clear_cache();
-- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦