ie-developers / ie-questions

public questions for ie students.
10 stars 0 forks source link

Ruby:クラスとモジュールについての疑問 #3

Closed kazuminn closed 9 years ago

kazuminn commented 10 years ago

メタプログラミングRuby (初版 p.53)に 「ClassクラスはModuleクラスのサブクラスである。つまり、クラスもモジュールである」 と記述されています。

が、モジュールクラスを継承するとモジュールなのですか?

atton commented 10 years ago

えーっと、その質問には2つの解釈の仕方があってですね

  1. Module Class を継承したものは Module か これは素直にクラスの継承の仕方なので yes。 A Class を継承したものは A の method を再利用することができる、みたいな「モジュール」の話ではなくて「クラス」の話。
  2. Module Class を継承したものにモジュールの性質が付くのか これはちょっと答えにくい。 たぶんここで言ってる「モジュール」はネームスペース的な話で、どうして Hoge::Fuga ができるか、みたいな話だった場合。 その辺りの実行の流れは詳しく知らないので調べてみないと分からない。

でも、Module を継承しているのは Class と Module クラスしか無いみたいなので、その点に関しては「Module を継承したのはモジュールか」って点は正しいとは思う。(Module を継承しているのが Class しかなくて Class はモジュールだから理屈だけは通ってる的な)

atton commented 10 years ago

でも、Module を継承しているのは Class と Module クラスしか無い

はこんな感じ

[20] pry(main)> Module.constants.map{|a| Module.const_get(a)}.select{|a| a.respond_to?(:ancestors)}.select{|a| a.ancestors.include?(Module)}
=> [Module, Class]
hanachin commented 10 years ago
# ClassクラスはModuleクラスを継承している
Class.ancestors
# => [Class, Module, Object, PP::ObjectMixin, Kernel, BasicObject]
# http://docs.ruby-lang.org/ja/2.1.0/method/Module/i/ancestors.html

# ClassクラスはModuleクラスのサブクラス
Class.superclass
# => Module
# http://docs.ruby-lang.org/ja/2.1.0/method/Class/i/superclass.html

# ClassクラスはClassクラスのインスタンス
Class.class
# => Class
# http://docs.ruby-lang.org/ja/2.1.0/method/Object/i/class.html

# なのでClassクラス(Classクラスのインスタンス)はModuleクラスのインスタンスでもある
Class.is_a?(Module)
# => true
# > オブジェクトが指定されたクラス mod かそのサブクラスのインスタンスであるとき真を返します。
# http://docs.ruby-lang.org/ja/2.1.0/method/Object/i/kind_of=3f.html

# もちろん、Classクラス以外のRubyのクラスも、Classクラスのインスタンス
[Module, Object, String, Array, Regexp].all? {|c| c.is_a?(Class) }
# => true
# > Ruby では、クラスもオブジェクトの一つで Classクラスの インスタンスです
# http://docs.ruby-lang.org/ja/2.1.0/doc/spec=2fdef.html#class

>クラスもモジュールである<

ナ ナンダッテー!! Ω ΩΩ

kazuminn commented 10 years ago

@atton- さん

Hoge::Fuga

ってなんだーってなってるのですが

kazuminn commented 10 years ago

@hanachin さん

ClassクラスはClassクラスのインスタンス

  Class.class

=> Class

http://docs.ruby-lang.org/ja/2.1.0/method/Object/i/class.html

ここでのインスタンスってnewされた方ですか? それとも継承することもインスタンス化が含まれているのですか?

atton commented 10 years ago

@kazuminn

Hoge::Fuga

ってなんだーってなってるのですが

モジュールの機能ですね。名前空間を分けることができるやつです。 最初の質問で「モジュール」って言ってた機能がこれかなー、と思って。 ちなみに解説しておくと

[2] pry(main)> module Hoge  # Hoge Module を定義
[2] pry(main)*   Fuga = 100    # Hoge の中に Fuga を定義
[2] pry(main)* end  
=> 100
[3] pry(main)> Fuga # Fuga は Hoge の中なので参照できない
NameError: uninitialized constant Fuga
from (pry):5:in `__pry__'
[4] pry(main)> Hoge::Fuga  # Hoge::Fuga と書けば参照できる
=> 100
[5] pry(main)> Fuga = 200  # Fuga を定義こともできる
=> 200
[6] pry(main)> Fuga        # Fuga と書けば Hoge::Fuga ではなくて Fuga
=> 200
[7] pry(main)> Hoge::Fuga  # Hoge::Fuga と書けば Fuga ではなくて Hoge::Fuga
=> 100

みたいな感じで「同じ名前(変数名)」を定義するために「このモジュールの下」の「名前」みたいに参照する、ってことですね。 A と B::A と C::B::A みたいに A を「Bの中のA」「Cの中のBの中のA」という風に名前の空間を分けることができることができる機能をモジュールは持ってるのです

hanachin commented 10 years ago

ここでのインスタンスってnewされた方ですか? それとも継承することもインスタンス化が含まれているのですか?

クラスを宣言するとClassクラスのインスタンスができる感じです

# StringクラスをnewするとStringクラスのインスタンスがかえる
String.new.class
# => String

# 同じようにClassクラスをnewするとClassクラスのインスタンスがかえる
Class.new.class
# => Class

# クラスCを定義すると
class C; end
# => nil

# ClassクラスのインスタンスCができる!
C.class
# => Class

# 何も指定しない場合Objectクラスを継承する
C.superclass
# => Object
kazuminn commented 10 years ago

@hanachin さん よくわかりました。ありがとうございます。

kazuminn commented 9 years ago

でも、Module を継承しているのは Class と Module クラスしか無い

Module#ancestor は、selfも戻り値とし、上記はModule#ancestorによって導き出されているので、Moduleクラスを継承しているのはClassしかないとゆうことですよね。

あと、「でも」と書かれていますが、「1,2の結果より」との解釈でいいですか?

atton commented 9 years ago

でも、Module を継承しているのは Class と Module クラスしか無い

Module#ancestor は、selfも戻り値とし、上記はModule#ancestorによって導き出されているので、Moduleクラスを継承しているのはClassしかないとゆうことですよね。

その通り。

あと、「でも」と書かれていますが、「1,2の結果より」との解釈でいいですか? 1,2 の結果よりってどういう意味だろう。

『でも』は 『「モジュールを継承していてクラスで無いもの」があるか調べたんだけれど』 って意味かなー。

[20] pry(main)> Module.constants.map{|a| Module.const_get(a)}.select{|a| a.respond_to?(:ancestors)}.select{|a| a.ancestors.include?(Module)}
=> [Module, Class]

ってやったら Module と Class しか無かったので。

kazuminn commented 9 years ago

なるほどです。ありがとうございました