アプリ版:「スタンプのみでお礼する」機能のリリースについて

define_singleton_methodについて

1.9.1p378を使用しています。

メタプログラミングに興味があって、
Classに動的に生成したmethodを追加する方法を調べてみると
色々な教科書にdefine_methodを使う例が書いてあるのを見つけました。

しかし、実際にプログラムしてみると"undefined method"になってしまいます。

Class.methods.grep /define/
してみると、"define_singleton_method"というものがあり、
define_methodの代わりに使ってみたら一応期待通りに動作しました。

googleで調べてみてもdefine_singleton_methodについて解説が見つけられませんでした。

1.9系になって名前が変わったのでしょうか?
それとも似て非なるものなのでしょうか?

詳しい方、教えてください。<(_ _)>

A 回答 (3件)

define_singleton_methodは1.9で追加されたもので、Objectクラスのメソッドです。



一方define_methodはModuleクラスのprivateメソッドなので、ModuleかClassの中から呼ばないといけません。
(ClassクラスはModuleクラスのサブクラス。Rubyのprivateはサブクラスからも見える)

define_methodであとからメソッドを追加しようとする場合、直接外からは呼べないので、間接的にdefine_methodを呼ぶメソッドを作成しておくか、一度Classを開くなどをやらないといけませんが、

define_singleton_methodを使えば、そんなことはせずに、簡単にできるということです。
    • good
    • 0

>Classに動的に生成したmethodを追加する方法を調べてみると


と書きながら、補足のサンプルを見ると、オブジェクトの特異メソッドを定義しようとしているように見えるのですが。もしそうだとすると、特異クラスを使って、

module L
class R
module Login
 def login_setup()
  puts "Login login_setup()"
  class << self
   define_method(:login) do |id,pass|
    puts "login() #{id} , #{pass}"
   end
  end
 end
end
end
end

この回答への補足

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

補足日時:2010/05/23 11:20
    • good
    • 0

ダメだったコードと、OKだったコードを補足にどうぞ。

この回答への補足

OKだったコード
module L
class R
module Login
 def login_setup()
  puts "Login login_setup()"

  # :loginの代わりに"login"でもよいのは理解している
  define_singleton_method(:login) do |id,pass|
   puts "login() #{id} , #{pass}"
  end

 end
end
end
end


class Y
 include L::R::Login

 def initialize
  login_setup() # class Yのインスタンスにlogin()が追加されるのを期待
 end
end


#
# MAIN
#
c = Y.new
p c.methods - Object.methods #=>[:login, :login_setup]
if c.respond_to?(:login)
 c.login("A", "B") #=>login() A , B
end

[NG]
1) define_singleton_method の代わりに define_method
2) __send__ 使用でdefine_method呼び出し(private methodを強制的に呼ぶ方法)
3) 他、「Rubyクックブック」などに書いてある方法=>全滅

補足日時:2010/05/22 09:46
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!