块中定义的方法属于哪个class?
Which class does a method defined inside a block belong to?
这是一个 class
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
如果一个方法定义在 class 之外,它将成为 class Object
内部的私有方法。为什么块内定义的方法成为 NilClass
的一部分而不是 class Foo
的一部分?
如果你想检索 class 定义的方法,你应该明确地做:
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
首先,m1
returnsputs
的结果,即nil
。
其次,使用您当前的代码,m1
方法是为 Object
class 定义的,因为默认情况下块保留其上下文,而不仅仅是局部变量(它始终如此) ),还有 'current object' 和 'current class'。如果您希望您的定义按预期工作,您可以使用 class_eval
,它会更改块内的当前 class(在不同的上下文中执行此块:
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>
这是一个 class
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
如果一个方法定义在 class 之外,它将成为 class Object
内部的私有方法。为什么块内定义的方法成为 NilClass
的一部分而不是 class Foo
的一部分?
如果你想检索 class 定义的方法,你应该明确地做:
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
首先,m1
returnsputs
的结果,即nil
。
其次,使用您当前的代码,m1
方法是为 Object
class 定义的,因为默认情况下块保留其上下文,而不仅仅是局部变量(它始终如此) ),还有 'current object' 和 'current class'。如果您希望您的定义按预期工作,您可以使用 class_eval
,它会更改块内的当前 class(在不同的上下文中执行此块:
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>