块内定义的方法属于哪个类?

时间:2018-07-24 11:45:51

标签: ruby ruby-2.3

这是一堂课

class Foo
  def test_method(&c)
    puts "inside test method"
    c.call
  end
end 

现在,如果我在块内定义一个方法

f = Foo.new
f.test_method do 
  def m1
    puts "inside the method m1 defined inside the block"
  end
  puts m1.class
end

该块的输出为NilClass

如果在类外部定义了方法,则它将成为类Object内部的私有方法。为什么在块内定义的方法成为NilClass而不是类Foo的一部分?

2 个答案:

答案 0 :(得分:4)

首先,m1返回puts的结果,即nil

第二,在当前代码中,为m1类定义了Object方法,因为默认情况下block保留了它的上下文,不仅对于局部变量(它总是如此),而且对于'当前对象”和“当前类别”。如果您希望自己的定义按预期工作,则可以使用class_eval,它会更改块中的当前类(在不同的上下文中执行该块:

class Foo
  def test_method(&c)
    puts 'inside test method'
    self.class.class_eval(&c)
  end
end
f = Foo.new
f.test_method do
  def m1
    # anything
  end
end

Foo.instance_methods.grep(/m1/)
# => [:m1]
f.m1
# => not an error
Object.new.m1
# => NoMethodError: undefined method `m1' for #<Object:0x00000001c9b4f8>

答案 1 :(得分:0)

如果要检索定义该方法的类,则应明确地进行操作:

Foo.new.test_method do 
  def m1; :content_does_not_matter; end
  puts method(:m1).inspect
end  
#⇒ #<Method: Object#m1>

一个人可能使用Method#owner来检索所有者:

method(:m1).owner
#⇒ Object