-- / --
--
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

12 / 24
Tue

「1,500 万」 ではなく 「15,00 万」 だろ、 とか思う Ziphil です。

今日の昼ごろ、 このエントリーでこんなコードを書きました。

class String
  def camel_case
    name = split("_")
    ([name.first] + name[1, name.size - 1].map{|i| i.capitalize}).join
  end
end
class Module
  def def_java(*names)
    names.each do |name|
      class_eval("alias :#{name.to_s.camel_case} :#{name} ")
    end
  end
end
#
class MainPanel < JPanel 
  def paint_component(graphics)
    super
    # 処理
  end
  def_java :paint_component
end

自分でコードを書いておいて、 何が起こっているのか実は把握してなかったり。 特に def_java :paint_component のあたりとか。 ということで、 何が起こっているのか調査してみます。

まずは状況を簡略化するために、 Test クラスに foo メソッドを定義し、 Module クラスを拡張して bar メソッドを定義した、 こんなコードを用意してみました。

class Module
  def bar
    puts("bar in Module")
  end
end
class Test
  def foo
    puts("foo in Test")
  end
end

さて、 このとき、 Test クラスの定義内で bar メソッドを呼び出すことができます。

class Test
  def foo
    puts("foo in Test")
  end
  bar                    #=> bar in Module
end

これが不思議なんですよねぇ・・・。 bar メソッドは Module クラスで定義されたメソッドだから、 Module クラスのインスタンスに対してでしか呼び出せないはずです。 Test クラスの定義内で、 なぜ bar メソッドが呼べるんでしょう・・・?

ん、 そもそも、 Module クラスって何なんでしょうか? 確か、 クラスのクラスみたいな存在だったはず・・・。

p Test.class  #=> Class

あれ・・・? あ、 違う違う。 さらにそのスーパークラスでしたね。

p Test.class.superclass  #=> Module

よしよし。 Test が属するクラスは Class で、 その Class クラスは Module クラスを継承してるってわけですね。 ということは、 Module クラスで定義された bar メソッドは、 Class クラスのインスタンスに対して呼び出せることになります。 ん、 じゃ、 Test クラスの定義内で呼び出された bar メソッドのレシーバは、 Class クラスのインスタンスでなければならないはず・・・。 クラスの定義内の self のクラスを調べてみましょう。

class Test
  def foo
    puts("foo in Test")
  end
  p self                 # => Test
  p self.class           # => Class
end

予想通り! でも、 メソッド定義の内部だと・・・?

class Test
  def foo
    puts("foo in Test")
    p self               # => #<Test:0x1567908>
    p self.class         # => Test
  end
end
Test.new.foo

・・・そりゃそうですよねぇ。 これでかなり掴めてきました。 クラス定義内でメソッド定義外では、 self がそのクラスそのものになり、 メソッド定義内になると、 self はそのクラスのインスタンスになります。 と、 こういう感じですね。

これが分かると少し気になることがあります。 インスタンス変数のゲッタやセッタを定義するときに attr_reader :hoge とか attr_accessor :huga とか書きますが、 これってもしかして Module クラスのメソッドなのでは・・・? 早速調べてみます。

p Module.methods.include?(:attr_accessor)  #=> false

あれ、 違う・・・? どういうこと? じゃ、 Module クラスのインスタンス作って、 attr_accessor メソッドを呼んでみましょう。

p Module.new.attr_accessor  #=> private method `attr_accessor' called for #<Module:0x14876f4> (NoMethodError)

ははーん。 private だったんですねぇ。 なるほどなるほどー。 ということは・・・?

p Module.private_methods.include?(:attr_accessor)  #=> true

やっぱりやっぱり! あー、 これですっきりしました。 つまり、 Module クラスで attr_accessor メソッドが定義されてるわけですね! ということは、 attr_accessor ってのは予約語でもなんでもなかったということです。 たいていの IDE が attr_accessor を予約語っぽくハイライトしてたから、 勘違いしてましたよ。

もう、 途中で 「Class」 とか 「Module」 ってのが、 クラスを表してるのか、 Module クラスのインスタンスを表してるのか、 頭がごちゃごちゃになりました。 何か不思議ですねぇ・・・、 Ruby の Class の世界。

スポンサーサイト

comment ×0
コメント
管理者にだけ表示を許可する
 
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。