【问题标题】:How to use define_method inside initialize()如何在 initialize() 中使用 define_method
【发布时间】:2013-10-22 12:03:57
【问题描述】:

尝试在 initialize 中使用 define_method,但得到 undefined_method define_method。我做错了什么?

class C
  def initialize(n)    
    define_method ("#{n}") { puts "some method #{n}" }    
  end
end

C.new("abc") #=> NoMethodError: undefined method `define_method' for #<C:0x2efae80>

【问题讨论】:

  • 你想做什么?
  • 没什么具体的,试着看看我如何使用define_method动态定义一个方法

标签: ruby metaprogramming


【解决方案1】:

我怀疑你在寻找define_singleton_method

define_singleton_method(symbol, method) → new_method
define_singleton_method(symbol) { block } → proc

在接收器中定义一个单例方法。 method 参数可以是ProcMethodUnboundMethod 对象。如果指定了块,则将其用作方法体。

如果您在self.class 上使用define_method,您将创建新方法作为整个类的实例方法,这样它就可以作为该类的所有实例的方法使用。

你会像这样使用define_singleton_method

class C
  def initialize(s)    
    define_singleton_method(s) { puts "some method #{s}" }    
  end
end

然后:

a = C.new('a')
b = C.new('b')
a.a # puts 'some method a'
a.b # NoMethodError
b.a # NoMethodError
b.b # puts 'some method b'

如果您的initialize 做到了:

self.class.send(:define_method,n) { puts "some method #{n}" }    

然后你会得到:

a.a # puts 'some method a'
a.b # puts 'some method b'
b.a # puts 'some method a'
b.b # puts 'some method b'

这可能不是您想要的。创建一个新实例并导致整个类发生变化是相当奇怪的。

【讨论】:

【解决方案2】:

如下操作:

class C
  def initialize(n)    
    self.class.send(:define_method,n) { puts "some method #{n}" }    
  end
end

ob = C.new("abc")
ob.abc
# >> some method abc

Module#define_method 是一个 private 方法 也是一个 class 方法。你的方法不起作用,因为你试图在 C 的实例上调用它.你必须在C上调用它,在你的情况下使用#send

【讨论】:

  • 它有效。你能解释一下为什么我的早期版本不正确吗?
  • @Bala:请注意,o = C.new('pancakes') 将留下ob.abcob.pancakeso.abco.pancakes 作为有效的方法调用。大家确定这是本意吗?
  • @muistooshort:有趣的评论。虽然没有意图,但现在我正在考虑如何使其成为特定对象(单例)。
【解决方案3】:

你快到了。只需用self.class指向类,甚至不需要使用:send

class C
  def initialize(n)    
    self.class.define_method ("#{n}") { puts "some method #{n}" }    
  end
end
ob = C.new('new_method')
ob2 = C.new('new_method2')
# Here ob and ob2 will have access to new_method and new_method2 methods

您也可以将它与:method_missing 一起使用,向您的班级教授新方法,如下所示:

class Apprentice
  def method_missing(new_method)
    puts "I don't know this method... let me learn it :)"
    self.class.define_method(new_method) do
      return "This is a method I already learned from you: #{new_method}"
    end
  end
end
ap = Apprentice.new
ap.read
=> "I don't know this method... let me learn it :)"
ap.read
=> "This is a method I already learned from you: read"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-19
    • 2019-09-29
    • 2015-08-13
    • 2010-10-19
    • 2023-04-04
    • 2017-01-11
    • 2011-11-03
    • 1970-01-01
    相关资源
    最近更新 更多