在拨打超级电话时不要传递阻止

时间:2018-01-16 10:29:33

标签: ruby

如何为super电话设置阻止为空?

class A
  def foo
    if block_given?
      result = yield 
      # do stuff with the yield result
    end
    # some more code
  end
end

class B < A
  def foo
    block_result = yield
    # process block results and store it
    # ...
    super
  end
end

B.new.foo { puts "block called" }
# => block called
# => block called

我不想两次屈服。是否有可能{class 1}}中的block_given?返回false?

背景是我不拥有A类,我不能改变它的A方法,但我想避免两次调用我的块。我也不想将伪/空块传递给super,因为foo的{​​{1}}方法的行为在给出块时会发生变化。

1 个答案:

答案 0 :(得分:15)

实际上并不那么明显。从documentation我们知道:

  • 调用super传递所有参数
  • 调用super()不传递参数

文档没有说明这只适用于位置和关键字参数。 super()仍然传递给定的块!

您必须通过调用:

显式取消设置块
super(&nil)

这是如何工作的?

您可能知道可以使用明确的block argument定义方法:

def foo(&block)
  # ...
end

并且您可以将其作为块传递给另一个方法:(其他方法可能是super

def foo(&block)
  super(&block)
end

现在,如果在调用方法时传递一个块,相应的block变量将是Proc的一个实例:

def foo(&block)
  p block_given: block_given?, block: block
end

foo {}
#=> {:block_given=>true, :block=>#<Proc:0x00007ff4990d0030>}

如果你在没有通过阻止的情况下调用它,block变量将只是nil

foo
#=> {:block_given=>false, :block=>nil}

因此,如果没有给出阻止,blocknil

super(&block)

变为:

super(&nil)