Controlling superclass argument pass-through in Ruby
Tags: rubytapasfreebies, classes, objectorienteddesign, oop
Published: 2020-11-08 18:25:05

---
title: Controlling superclass argument pass-through in Ruby
published: true
date: 2020-10-16 15:00:13 UTC
tags: RubyTapasFreebies,classes,ObjectOrientedDesign,oop
canonical_url: https://avdi.codes/controlling-superclass-argument-pass-through-in-ruby/
---

In Ruby class-based programming, superclass versions of subclass methods are always invoked explicitly using the `super` keyword. There are some nuances to using `super` though, particularly when it comes to passing (or _not_ passing) arguments and blocks along to the base class. In this sample from from the [RubyTapas](https://www.rubytapas.com/) archives, we’ll talk about some of those “gotchas”.

**Director’s commentary:** This was originally published as [RubyTapas](https://www.rubytapas.com/)#14 in October 2012. I used to have a habit of saying “as you know” in my scripts, I think because I was afraid my audience would see something they already knew at the start of the episode and think “oh this is nothing new”. I don’t say that kind of thing as much anymore, although I still say “as you _may_ know” from time to time. I’ve become a lot more comfortable just stating my background material and trusting the viewer to situate themselves with regard to it.

I’m a bit mad at myself for not coming up with a more “real” example here; I think that makes it harder to follow. This was back in the era of three episodes a week (!) though, so I’ll cut myself some slack for hasty writing.

Scroll down for the video script and code.

<script src="https://fast.wistia.com/assets/external/E-v1.js" async></script>

 ![](https://fast.wistia.com/embed/medias/hmewmz4ctn/swatch)

Let’s talk about calling superclass methods.

As you know, when class `Child` inherits from class `Parent`, and both define a method `#hello`, the `Child` can reference the `Parent`‘s implementation of `#hello`, using `super`.

```
class Parent
  def hello(subject="World")
    puts "Hello, #{subject}"
  end
end


class Child < Parent
  def hello(subject)
    super(subject)
    puts "How are you today?"
  end
end


Child.new.hello("Bob") 


Hello, Bob How are you today?
```

If we simply want to call the parent implementation with the same arguments that were passed to the child implementation, we can omit the arguments to `super`. This **only** works if we leave off the parentheses as well.

```
class Child < Parent
  def hello(subject)
    puts super
    puts "How are you today?"
  end
end

```

This makes our code less brittle, because changes to a parent method’s parameter list won’t mean having to hunt around and update every `super` call that invokes it.

Sometimes we may want to force zero arguments to be passed to the superclass method. In that case, it’s important to remember to explicitly supply empty parentheses instead of leaving them off.

Here’s a version of `Child` that takes a special flag to indicate that it should use its default subject. When the flag is passed, it calls `super` with empty parentheses, forcing the superclass method to resort to the default value for `subject`.

```
class Child < Parent
  def hello(subject=:default)
    if subject == :default
      super() 
      puts "How are you today?"
    else
      super(subject)
      puts "How are you today?"
    end
  end
end


Child.new.hello(:default)


Hello, World How are you today?
```

There’s a catch to this, though: even with explicit empty parens, calling super will still automatically pass along any block given to the child method.

To show what I mean, let’s modify the parent class method to take a block, and then pass a block to the call to `#hello`.

```
class Parent
  def hello(subject="World")
    puts "Hello, #{subject}"
    if block_given?
      yield
      puts "Well, nice seeing you!"
    end
  end
end


Child.new.hello(:default) do
  puts "Hi there, Child!"
end
# >> Hello, World
# >> Hi there, Child!
# >> Well, nice seeing you!
# >> How are you today?


Hello, World Hi there, Child! Well, nice seeing you! How are you today?
```

As you can see, the output is a little mixed-up due to the block being unexpectedly passed-through despite the empty argument list to `super`.

In order to suppress the block being passed through, we have to use the special argument `&nil`:

```
class Child < Parent
  def hello(subject=:default)
    if subject == :default
      super(&nil) 
      puts "How are you today?"
    else
      super(subject, &nil)
      puts "How are you today?"
    end
  end
end


Child.new.hello(:default) do
  puts "Hi there, Child"
end


Hello, World How are you today?
```

This less-than-obvious technique eliminates the possibility of a block being implicitly passed through to the superclass method.

I have some other tricks involving the `super` keyword, but I’ll save them for a [future episode](https://www.rubytapas.com/2012/10/29/episode-016-super-in-modules/#tapas_script). [Happy hacking!](https://www.rubytapas.com/2012/10/29/episode-016-super-in-modules/#tapas_script)