Calling a Superclasss Method

Calling a Superclass s Method

Problem

When overriding a class's method in a subclass, you want to extend or decorate the behavior of the superclass, rather than totally replacing it.

Solution

Use the super keyword to call the superclass implementation of the current method.

When you call super with no arguments, the arguments to your method are passed to the superclass method exactly as they were recieved by the subclass. Here's a Recipe class that defines (among other things) a cook method.

class Recipe # … The rest of the Recipe implementation goes here. def cook(stove, cooking_time) dish = prepare_ingredients stove << dish wait_for(cooking_time) return dish end end

Here's a subclass of Recipe that tacks some extra behavior onto the recipe. It passes all of its arguments directly into super:

class RecipeWithExtraGarlic < Recipe def cook(stove, cooking_time) 5.times { add_ingredient(Garlic.new.chop) } super end end

A subclass implementation can also choose to pass arguments into super. This way, a subclass can accept different arguments from its superclass implementation:

class BakingRecipe < Recipe def cook(cooking_time, oven_temperature=350) oven = Oven.new(oven_temperature) super(oven, cooking_time) end end

 

Discussion

You can call super at any time in the body of a methodbefore, during, or after calling other code. This is in contrast to languages like Java, where you must call super in the method's first statement or never call it at all. If you need to, you can even call super multiple times within a single method.

Often you want to create a subclass method that exposes exactly the same interface as its parent. You can use the *args constructor to make the subclass method accept any arguments at all, then call super with no arguments to pass all those arguments (as well as any attached code block) into the superclass implementation. Let the superclass deal with any problems with the arguments.

The String#gsub method exposes a fairly complicated interface, but the String subclass defined here doesn't need to know anything about it:

class MyString < String def gsub(*args) return "#{super} -- This string modified by MyString#gsub (TM)" end end str = MyString.new("Here's my string") str.gsub("my", "a") # => "Here's a string -- This string modified by MyString#gsub (TM)" str.gsub(/m| s/) { |match| match.strip.capitalize } # => "Here's MyString -- This string modified by MyString#gsub (TM)"

If the subclass method takes arguments but the superclass method takes none, be sure to invoke super with an empty pair of parentheses. Usually you don't have to do this in Ruby, but super is not a real method call. If you invoke super without parentheses, it will pass all the subclass arguments into the superclass implementation, which won't be able to handle them.

In the example below, calling just super would result in an ArgumentError: it would pass a numeric argument into String#succ!, which takes no arguments:

class MyString def succ!(skip=1) skip.times { super() } self end end str = MyString.new('a') str.succ!(3) # => "d"

Invoking super works for class methods as well as instance methods:

class MyFile < File def MyFile.ftype(*args) return "The type is #{super}." end end File.ftype("/bin") # => "directory" MyFile.ftype("/bin") # => "The type is directory."

Категории