我一直在编写DSL,我试图让一个动态定义的方法可以从lambda中访问。除非你尝试做一个setter something=
,否则这种方法很好。在这种情况下,lambda调用只会设置一个局部变量。
简化示例:
class Caller
attr_accessor :cmd
def callme
self.class.send(:define_method, "something") { puts "Retrieve Something" }
self.class.send(:define_method, "something=") {|val| puts "Set Something = #{val}" }
instance_exec &cmd
end
end
c = Caller.new
c.cmd = lambda { something = 1 }
c.callme
如果我使用self.something=
,这也可以正常工作。然而,在DSL的情况下,这并不理想。
是否可以在方法前面没有self.
的情况下使其工作?
答案 0 :(得分:2)
这与块或动态定义的方法完全无关。它只是简单的基本Ruby语法:
foo = bar
是局部变量赋值。总是
self.foo = bar
是方法调用。
是否可以在方法前面没有
self.
的情况下使其工作?
没有
这只是基本的Ruby语法。 define_method
元编程,instance_exec
,代码示例中的块只是一个红色的鲱鱼,问题可以用很多更简单的例子来证明:
def foo=(*)
puts 'I was called!'
end
foo=('bar') # even removing spaces and adding parentheses won't help!
self.foo = 'bar'
# I was called!
另请注意,foo=
为private
,但实际上是使用显式接收方调用的(private
方法不合法)。对于private
方法的规则中的setter方法来说,这是一个特殊的例外,因为它们根本无法被调用,正是因为它们总是被解释为局部变量赋值。