In Ruby we can add new methods to existing classes.
How can we ensure that the name of our new method does not already
exists – I do not want to overwrite an existing method by accident. I
think there exists a way to list all currently existing methods of a
class, but the solution should work in future too( e.g. for Ruby 3.0
when predefined classes may have more predefined methods): I want
something like
class String
def very_useful_method
if already_defined(this_method)
puts ‘We are overwriting an existing method by accident’
Process.exit
end
end
end
But is there a way to call the original method instead of just quitting
out?
The super keyword does this, I’m not really sure what it is, a macro
maybe?
I just think of it as a function I have available in overridden methods,
like block_given?
Be aware that unless you specify its args, it will pass whatever params
the
method originally received.
class Parent
def self.ruby!(arg = nil)
puts “Parent.ruby!(#{arg.inspect})”
end
end
class Child1 < Parent
def self.ruby!(arg)
super
puts “Child1.ruby!(#{arg.inspect})”
end
end
class Child2 < Parent
def self.ruby!(arg)
super(12)
puts “Child2.ruby!(#{arg.inspect})”
end
end
class Child3 < Parent
def self.ruby!(arg)
super()
puts “Child1.ruby!(#{arg.inspect})”
end
end
I noticed that too. Super works fine in cases of inheritance, but the
example wasn’t inheriting, it was reopening.
Though my first instinct was to try to use the “this” object in the
“else…” statement to just use the current object to call the original
method. But then I remembered ruby doesn’t have “this”.
But is there a way to call the original method instead of just quitting
out?
If you want to know if you can conditionally define the method and skip
the exit, yes, you can. Just leave out the else clause of the example.
That way, your method is called only if the original one didn’t already
exist. I used this once to implement Enumerable#none? only under
versions of Ruby where that method was not yet implemented.
If you want to have a kind of functionality similar to that provided by
the super keyword, you can do that too:
class String
if method_defined?(:my_method) then
alias :my_method_orig :my_method
end
def my_method
# Maybe do some extra stuff here.
…
# Call the original method if there is one.
if methods.include?("my_method_orig") then
my_method_orig
end
# Maybe do more extra stuff here.
...
end
end
This will alias the original instance of my_method, if there is one, to
my_method_orig. Your new my_method definition can call the alias if it
exists and skip it otherwise. I suppose this would be good for
instrumenting methods to add logging and the like, but I would take care
with using this generally since it can make some unnecessarily
complicated code.
Though my first instinct was to try to use the “this” object in the
“else…” statement to just use the current object to call the original
method. But then I remembered ruby doesn’t have “this”.
In Ruby, the current object is “self”. Inside a ‘class’ definition, it’s
the class object.
On Thu, Sep 30, 2010 at 11:32 PM, Jeremy B. [email protected] wrote:
If you want to have a kind of functionality similar to that provided by
This will alias the original instance of my_method, if there is one, to
my_method_orig. Your new my_method definition can call the alias if it
exists and skip it otherwise. I suppose this would be good for
instrumenting methods to add logging and the like, but I would take care
with using this generally since it can make some unnecessarily
complicated code.
Shouldn’t we be using respond_to? instead of method_defined? or
methods.include?.
This way, if the method is handled dynamically through method_missing
you can check that too, and not “override” the behaviour.
Shouldn’t we be using respond_to? instead of method_defined? or
methods.include?.
respond_to? only works on instances of objects, not when you’re within
the class.
You could do “new.respond_to? …” but if the initialize method needs
arguments, you’ll have to provide them.
Ah, you are right, I missed that we were not in an instance…
Anyway, be careful then with this technique, cause if the instance
would be handling that method call with method_missing you will not
know it using the above.
Regards,
Jesus.
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.