8

I have a class Duck with an initialize method that yields to a block:

class Duck
  def initialize()
    if block_given?
      yield(self)
    end
  end
end

and a class TalkingDuck that greets the programmer when it is initialized.

class TalkingDuck < Duck
  def initialize()
    super()
    puts 'I am a duck'
  end
end

When I call the constructor TalkingDuck.new with a block, I don't want this block to be executed. This:

TalkingDuck.new { puts 'Quack' }

should only print I am a duck, but not Quack. How can I prevent the block from being executed?

sawa
  • 165,429
  • 45
  • 277
  • 381
DarkWiiPlayer
  • 6,871
  • 3
  • 23
  • 38
  • 3
    See @Stefan’s great answer [here](https://stackoverflow.com/questions/48279119/dont-pass-block-when-calling-super?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa). – Cary Swoveland Jun 04 '18 at 08:30

1 Answers1

9

Ruby implicitly passes the arguments and the block of the current method to super. With arguments, that can be avoided by explicitly calling super with no arguments (super()). The same thing can be done with blocks. A block can be passed to a method with &:

greet = proc { puts 'hi' }
do_some_stuff(&greet)

you can explicitly avoid passing a block with &nil. In this case, this means you can change the initialize method of TalkingDuck to:

def initialize()
  super(&nil)
  puts 'I am a duck'
end

and it will explicitly discard any given block and not pass it further up to super, but you can still handle the block yourself inside the method.

DarkWiiPlayer
  • 6,871
  • 3
  • 23
  • 38
  • 1
    Note: I found this information in [this](https://stackoverflow.com/questions/50670794/what-does-supernil-do-in-ruby) stackoverflow question, but since that question was `what does X do?`, nobody looking for `how do I do Y?` would likely find it. Alternative / better answers are, of course, still very much welcome :) – DarkWiiPlayer Jun 04 '18 at 07:13
  • 1
    If your method takes any arguments, then passing `&nil` to prevent passing a block up prevents the default "pass all the arguments when you call `super` with no arguments", so you'll need to enumerate the arguments you want to pass up: `super arg1, arg2,...,&nil` – Simple Lime Jun 04 '18 at 08:47
  • _"calling super with nil"_, i.e. `super(nil)` passes a single argument `nil` to super. You have to call `super()` in order to pass no arguments. That's quite a difference. – Stefan Jun 05 '18 at 09:41