daxelrod
daxelrod

Reputation: 2589

Why is 'super' a keyword rather than a method in Ruby?

In Ruby, super is a keyword rather than a method.

Why was it designed this way?

Ruby's design tends toward implementing as much as possible as methods; keywords are usually reserved for language features that have their own grammar rules. super, however, looks and acts like a method call.

(I know it would be cumbersome to implement super in pure Ruby, since it would have to parse the method name out of caller, or use a trace_func. This alone wouldn't prevent it from being a method, because plenty of Kernel's methods are not implemented in pure Ruby.)

Upvotes: 9

Views: 382

Answers (3)

d11wtq
d11wtq

Reputation: 35318

It behaves a little differently, in that if you don't pass arguments, all of the current arguments (and block, if present) are passed along... I'm not sure how that would work as a method.

To give a rather contrived example:

class A
  def example(a, b, c)
    yield whatever(a, b) + c
  end
end

class B < A
  def example(a, b, c)
    super * 2
  end
end

I did not need to handle the yield, or pass the arguments to super. In the cases where you specifically want to pass different arguments, then it behaves more like a method call. If you want to pass no arguments at all, you must pass empty parentheses (super()).

It simply doesn't have quite the same behaviour as a method call.

Upvotes: 5

amnn
amnn

Reputation: 3716

super doesn't automatically call the parent class's method. If you imagine the inheritance hierarchy of a ruby class as a list, with the class at the bottom and Object at the top, when ruby sees the the super keyword, rather than just check the the parent class, it moves up the entire list until it finds the first item that has a method defined with that name.

I'm careful to say item because it could also be a module. When you include a module in to a class, it is wrapped in an anonymous superclass and put above your class in the list I talked about before, so that means if you had a method defined for your class that was also defined in the module, then calling super from the class's implementation would call the module's implementation, and not the parent class's:

class Foo
  def f
    puts "Foo"
  end
end

module Bar
  def f
    puts "Bar"
    super
  end
end

class Foobar < Foo
  include Bar

  def f
    puts "Foobar"
    super
  end
end

foobar = Foobar.new
foobar.f
  # =>
  # Foobar
  # Bar
  # Foo

And I don't believe that it is possible to access this 'inheritance list' from the ruby environment itself, which would mean this functionality would not be available (However useful it is; I'm not every sure if this was an intended feature.)

Upvotes: 1

jefflunt
jefflunt

Reputation: 33954

Hm, good qustion. I'm not sure how else (besides using super) you would you reference the super version of a given method.

You can't simply call the method by name, because the way that polymorphism works (how it figures out which version of that method to actually call, based on the object class) would cause your method to call itself, spinning into an infinite set of calls, and resulting in a stack overflow.

Upvotes: 0

Related Questions