[#44431] コンストラクタの引数について&インスタンス変数の持ち方について — Akira Hayakawa <ruby@...>

度々オブジェクト指向についての質問ですいません。

17 messages 2008/01/04
[#44433] Re: コンストラクタの引数について&インスタンス変数の持ち方について — Yukihiro Matsumoto <matz@...> 2008/01/04

まつもと ゆきひろです

[#44469] pdf 作成 ライブラリ — "Luiz Aoki" <luizruby@...>

はじめまして、青木ルイスと申します、

14 messages 2008/01/12
[#44479] ファイル出力時のprintについて — m-hatake@... 2008/01/16

畠山と申します。

[#44483] format %g の丸めについて — 山崎雄介 <y-yamasaki@...>

山崎(ゆ)です。

14 messages 2008/01/16

[ruby-list:44530] Re: Module内Methodの名前空間

From: "Shingo Hagiwara" <rindou@...>
Date: 2008-01-23 05:22:13 UTC
List: ruby-list #44530
萩原です。お世話になりました。

るびきちさんの例にある

 def self.methodMB
   "methodMB"
 end
 private_class_method :methodMB   # ここがミソ
end

の部分で考えがかなりすっきりした気がします。
Moduleをincludeすると、initializeが呼ばれるように、クラスメソッドとインスタンスメソッドの差がModuleでも出てしまうのですね。てっきり、「::」で階層だけたどれば呼び出せるものと思っていました。

助かりました。ありがとうございます。

08/01/23 に rubikitch@ruby-lang.org<rubikitch@ruby-lang.org> さんは書きました:
> From: "Shingo Hagiwara" <rindou@gmail.com>
> Subject: [ruby-list:44528] Module内Methodの名前空間
> Date: Wed, 23 Jan 2008 11:38:18 +0900
>
> るびきちです。
>
> > 本題ですが、「名前空間を分けてModuleのMethodを使いたいな」と思い、includeせずに他のクラス内でModuleのMethodを使おうとしました。それで以下のようなコードを書きました。
>
> ClassAでincludeしたくないという意図でいいですか?
> クラス内ならばトップレベルの名前空間を汚染しないので、includeしちゃっていいと思いますが。
>
> > Code(1):
> > module ModuleA
> >   def methodMA()
> >     p "methodMA"
> >   end
> > end
> >
> > class ClassA
> >   def methodCA02()
> >     ModuleA::methodMA()
>
> この呼び出し方はモジュールのクラスメソッドを呼んでいるので、それが存在しないため
> NoMethodErrorとなります。
>
> おそらく、この目的からするとモジュール関数にするのがいいと思います。
> モジュール関数とは、モジュールのインスタンスメソッドであると同時にクラスメソッドでもあります。
>
> module ModuleA
>   def methodMA
>     "methodMA"
>   end
>   module_function :methodMA
> end
>
> class ClassA
>   def methodCA02
>     ModuleA::methodMA
>   end
> end
>
> class ClassB
>   include ModuleA
>   def methodCB02
>     methodMA
>   end
> end
>
> ClassA.new.methodCA02           # => "methodMA"
> ClassB.new.methodCB02           # => "methodMA"
>
>
>
> > のように無事に動きました。次に、「ModuleA::methodMA()でmethodMB()(methodMB()はModuleAのPrivate扱いにしたい)を使いたい」と思い、
>
> private_class_methodでクラスメソッドをprivateにできます。
> なお、クラスメソッドを定義するときはself.methodnameとするのがおすすめです。
> モジュール名・クラス名を変更してもメソッド定義部分は書き換え不要なので。
>
> module ModuleA
>   def self.methodMA
>     methodMB()
>   end
>
>   def self.methodMB
>     "methodMB"
>   end
>   private_class_method :methodMB   # ここがミソ
> end
>
> class ClassA
>   def methodCA02
>     ModuleA::methodMA
>   end
> end
>
> ClassA.new.methodCA02      # => "methodMB"
> ModuleA.methodMB rescue $! # => #<NoMethodError: private method `methodMB' called for ModuleA:Module>
>
>
> > と怒られました。同じModule内でのMethod呼び出しなのにと、個人的には分からなくなりました。
>
> 「モジュールのインスタンスメソッド」と「モジュールのクラスメソッド(特異メソッド)」の違いです。
>
> > そこで、「Moduleの中身は常にTopから辿らないと駄目なんだ」と思って、
>
> これはモジュールのメソッドの話ではなくて、定数探索の話です。
>
> > Code(4):
> > module ModuleA
> >   module ModuleAA
> >     CONS=1
> >   end
> >   def ModuleA::methodMA()
> >     p ModuleAA::CONS  #ModuleAから辿ってない
> >   end
> > end
>
> ここのModuleAA::CONSは現在のモジュールModuleAから辿るのでModuleA::ModuleA::CONSが参照されます。
> トップレベルからではありません。
> ちなみにモジュール(クラス)中から強制的にトップレベルの定数を参照するには
> 「::TOPLEVEL_CONSTANT」とします。
>
> module Foo
>   module Object; end
>   Object                        # => Foo::Object
>   ::Object                      # => Object
> end
>
>
>
> > class ClassA
> >   def methodCA01()
> >     p ModuleA::ModuleAA::CONS
> >   end
>
> ClassAにModuleAという定数が定義されていないのでトップレベルのModuleAが参照されます。
>
> リファレンスマニュアルより抜粋
>
> <quote>
> === 定数参照の優先順位
>
> 親クラスとネストの外側のクラスで同名の定数が定義されているとネストの外側の定数の方を
> 先に参照します。つまり、定数参照時の定数の探索順序は、最初にネスト関係を外側に向かっ
> て探索し、次に継承関係を上位に向かって探索します。
>
> 例:
>
> class Foo
>   CONST = 'Foo'
> end
>
> class Bar
>   CONST = 'Bar'
>   class Baz < Foo
>     p CONST             # => "Bar"      外側の定数
>     # この場合、親クラスの定数は明示的に指定しなければ見えない
>     p Foo::CONST        # => "Foo"
>   end
> end
>
> トップレベルの定数定義はネストの外側とはみなされません。したがってトップレベルの定数
> は、継承関係を探索した結果で参照されるので優先順位は低いと言えます。
>
> 例:
>
> class Foo
>   CONST = 'Foo'
> end
>
> CONST = 'Object'
>
> class Bar < Foo
>   p CONST               # => "Foo"
> end
>
> # 以下のように明示的にネストしていれば規則通り Object の定数
> # (ネストの外側)が先に探索される
> class Object
>   class Bar < Foo
>     p CONST             # => "Object"
>   end
> end
>
> 上位のクラス(クラスの継承関係上、およびネストの関係上の上位クラス)の定数と同名の定数
> (下の例で CONST) に代入を行うと、上位の定数への代入ではなく、そのクラスの定数の定義に
> なります。
>
> 例:
>
> class Foo
>   CONST = 'Foo'
> end
> class Bar < Foo
>   p CONST               # => "Foo"
>   CONST = 'Bar'         # Bar の定数 CONST を*定義*
>   p CONST               # => "Bar"  (Foo::CONST は隠蔽される)
>   p Foo::CONST          # => "Foo"  (:: 演算子で明示すれば見える)
> end
> </quote>
>
>
> --
> rubikitch
> Blog: http://d.hatena.ne.jp/rubikitch/
> Site: http://www.rubyist.net/~rubikitch/
>
>

In This Thread

Prev Next