JavaScript、Ajax、HTML5(API)、Ruby…Web及び関連技術の実験&情報公開&制作物紹介。

【覚書】[Ruby]続・トップレベルに定義したメソッドと同名のメソッドをクラスで定義した場合

| コメント(0) | トラックバック(0)

本日(日付が変わっちゃったので正確には昨日)、第14回Ruby東海勉強会に行ってきました。 そこでヒントをもらったので、半年前の記事に補足。

[おさらい]半年前に考えてたこと

def meth(a) p a; end
class Clazz
  def meth
    《トップレベルで定義した同名メソッドを self を引数に渡して呼び出したい!》
  end
end

こんなことしたい場合に、どうすれば良いのか?

↑こんなことを考えていました。

ポイントは以下の通り:

  • トップレベルで定義したメソッド = Kernelモジュールで定義されたprivateメソッド。
  • Kernelモジュールで定義されたメソッドと同名のメソッドを定義 = メソッドのオーバーライド。
  • privateメソッド = レシーバを指定して呼び出すこと(obj.methのように)が出来ない!(Rubyの仕様)

もう1つの解答

結論から書くと、前回考えた方法の他に、こんな方法で一応可能だった、ということが判明:

def meth(a) p a; end
@@main = self
class Clazz
    def meth
        @@main.send(:meth, self)
    end
end

解説

この書き方のポイントは以下:

  • トップレベルではmainというオブジェクト(Objectクラスのインスタンス)がselfになっている。
    • ↑のmainオブジェクトは他から直接参照できない。
      → 他から参照できる変数に代入してしまえ!
      → ということでクラス変数@@mainに入れてみました。
    • トップレベルのクラス変数 = Objectクラスのクラス変数 = 全てのクラスに共通で使えるクラス変数(なぜなら(BasicObject以外の)全てのクラスはObjectクラスを継承しているから)。
  • privateメソッドはレシーバ付きで呼び出すことが出来ない。
    • でもRubyにはメソッドにメッセージを送るメソッド send が用意されている。
      obj.send(:meth, 《arguments》)で、objオブジェクトのmethメソッドがたとえprivateメソッドでも呼び出し可能。
    • ということで
      @@main.send(:meth, self)
      でOK!
  • 前回は「同じオブジェクト内に属しているコトを期待して継承もとのメソッドを探す方法」に拘っていた。
    でも実はKernelモジュールのメソッドなんだから、別のオブジェクトにも属しているワケで。
    そっちから呼び出す方法を探れば良かった。それが今回の一番の収穫。

特に3番目。こんな単純でありながら目から鱗な方法を当時見落としていたとは。

あ、てことは、

def meth(a) p a; end
class Clazz
  def meth
    Object.new.send(:meth, self)
  end
end

これでもOKじゃん!

あ、もっというと、全てのクラスはClassクラス(のサブクラス)のインスタンスであり、ClasssuperclassObjectだから...

def meth(a) p a; end
class Clazz
  def meth
    Object.send(:meth, self)
  end
end

これでもいける。
全く同じコトはモジュールにも言えるから...

def meth(a) p a; end
class Clazz
  def meth
    Kernel.send(:meth, self)
  end
end

おおおー。これが見た目一番スマートだ。

トラックバック(0)

トラックバックURL: http://www.antimon2.atnifty.com/mt5/mt-tb.cgi/85

コメントする

カテゴリ

月別 アーカイブ

OpenID対応しています OpenIDについて

このブログ記事について

このページは、あんちもん2が2010年11月 6日 00:00に書いたブログ記事です。

ひとつ前のブログ記事は「第39回FLOSS桜山勉強会」です。

次のブログ記事は「Ruby東海第15回勉強会」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。