5

When redefining a class method I want to be able to call super, just as I would in a instance method.

For example, I have a class hi with a class method Hi.hi

class Hi
  def self.hi
    puts "hi"
  end
end

Hi.hi #=> "hi"

Now, Lets say i want to redefine self.hi

class Hi
  def self.hi
    super
    puts "Oh!"
  end
end

Hi.hi #=> NoMethodError: super: no superclass method `hi' for Hi:Class

Why doesn't this work?

I know I can get the same functionality using alias (as below), it just seems rather unnecessary.

class Hi
  class << self
    def new_hi
      old_hi
      puts "Oh!"
    end
    alias :old_hi :hi
    alias :hi :new_hi 
  end
end

Hi.hi #=> "hi\n Oh!"

Is there a better way to do this?

diedthreetimes
  • 4,086
  • 26
  • 38
  • Your new code with inheritance works fine for me (it puts _hi_ and _Oh_). What do you expect? if you want only _Oh!_ (you talked about redefine), then just don't call _super_. – knut Jul 19 '11 at 20:58
  • 1
    This question is a duplicate of [When monkey patching a method, can you call the overridden method from the new implementation](http://StackOverflow.Com/q/4470108/#4471202). – Jörg W Mittag Jul 19 '11 at 22:39

4 Answers4

4

Super works for child classes inherited from a parent class.

In your case alias is the only way. Or you can use alias_method:

alias_method :old_hi, :hi

def self.hi
  old_hi
  puts "Oh!"
end
kylewelsby
  • 4,031
  • 2
  • 29
  • 35
Vadim Golub
  • 1,655
  • 1
  • 11
  • 13
2

In the context of your code "super" refers to the Object class, since Object doesn't have a "hi" class level method it fails. "Hi" is an object of type "Class".

You don't have a super class defined so it defaults to object. You can see this at the console by typing "Hi.superclass"

The better way is to use traditional OOP to do this:

class Hi
  def self.hi
    puts "hi"
  end
end

class Ho < Hi
  def self.hi
    super
    puts "Oh!"
  end
end

The "class << self" syntax ends up creating an invisible intermediate class which does the inheritance chain.

It shouldn't matter that you created a new class since the new class extends the old one, they are interchangeable, except for the different output of self.hi()

Fab
  • 665
  • 3
  • 9
0

It does not work.Because the ancestors for your class Hi don't have a method hi.

  • This makes since, since the ancestors of Hi (or any class) is only ever class and object. I guess in the broader sense, why doesn't ruby have this functionality? Is it just an implementation challenge? – diedthreetimes Jul 19 '11 at 20:47
  • See knut's answer.He adds the method Hi to the object class(The base class for every class in ruby) –  Jul 19 '11 at 20:51
0

I don't understand your problem.

If you really redefine self.hi (Saying: super has a hi), then it works:

class Hi_super
  def self.hi
    puts "Oh - super!"
  end
end


class Hi < Hi_super
  def self.hi
    super
    puts "Oh!"
  end
end

Hi.hi

Or in another version:

class Object
  def self.hi
    puts "Oh - super!"
  end
end


class Hi 
  def self.hi
    super
    puts "Oh!"
  end
end

Hi.hi

Both version s results in

Oh - super!
Oh!
knut
  • 27,320
  • 6
  • 84
  • 112