我对Ruby块有疑问。 例如,我有一个Ruby类:
class NewClass
def initialize
@a = 1
end
def some_method
puts @a
end
end
当我做那样的事情时:
NewClass.new do |c|
c.some_method
end
一切都很好,但有没有可能做到这一点:
NewClass.new do
some_method
end
有什么想法吗?
答案 0 :(得分:2)
您当前的代码无论如何都会忽略该块,因为您不会yield
。对于您在第一个示例中尝试执行的操作,您需要yield self
中的initialize
惯用语。
为什么你首先需要一个块变量,想想你的第二个例子中some_method
的接收器是什么。如果没有明确的接收者,它就是顶级main
(除非这个代码是其他类的一部分,当然这个封闭的类将是self
)。见戴夫托马斯'博客文章Changing self in Ruby(或者Yehuda Katz' post,正如Niklas B.在评论中指出的那样)有关该主题的更多信息(评论清除了" proc调用"部分)。 / p>
编辑:所有这一切,这似乎有效,但我更喜欢yield self
版本和示例1:
class NewClass
def initialize
@a = 1
end
def some_method
puts "Hello: #@a"
end
def self.build(&block)
x = self.new
x.instance_eval(&block)
x
end
end
NewClass.build do
some_method
end
这允许您在没有块变量的情况下执行块,并返回类的新实例以分配给变量等。
答案 1 :(得分:2)
class NewClass
def initialize(&block)
@a = 1
instance_eval(&block)
end
def some_method
puts @a
end
end
NewClass.new do
some_method
end
答案 2 :(得分:0)
使用instance_eval
应该可以胜任。但除非你知道自己在做什么(而且这不只是出于懒惰),否则我会反对它,并采用你原来的方法。
def initialize(&block)
@a = 1
self.instance_eval(&block) if block_given?
end