首先,你需要理解在这里使用的 &
运算符。例如:
def a(&blk)
end
a(&Proc.new { true })
在 proc => 块的情况下,它也能将一些对象转换为procs,例如:
[1].map(&:class)
Symbol#to_proc
方法产生与以下代码相同的功能
[1].map(&Proc.new { |x| x.class })
我不确定官方文档的位置(欢迎提供指针),但从测试结果来看,&nil
实际上不会将任何块传递给该方法 - 它没有任何作用:
def a
block_given?
end
a {}
a &:puts
a &nil
现在已经解释清楚了,我可以继续说明为什么需要它。
如果您省略使用
super
时的括号,则会传递所有参数:
class A
def initialize arg
puts arg && block_given?
end
end
class B < A
def initialize arg
super
end
end
B.new(1) {}
如果您不希望发生这种情况,可以手动传递参数给
super
。但是,在此之后我将提到一个问题:
class A
def initialize arg1, arg2=nil
puts arg1 && !arg2
end
end
class B < A
def initialize arg1, arg2=nil
super arg1
end
end
B.new 1, 2
问题在于,虽然您可以防止传递位置参数和关键字参数,但这种方法
无法阻止块被传递:
class A
def initialize arg1
puts arg1 && block_given?
end
end
class B < A
def initialize arg1
super arg1
end
end
B.new(1) { }
由于某种原因,这里很重要的是它不发生,所以他们使用了一个我之前从未见过但似乎能够完成工作的成语:&nil
。它基本上是在说“将空内容传递为块”。我猜如果你不这样做,那么块会自动转发。
&nil
可能是一个空代码块)。 - Guillaume