How to prevent overwriting methods by accident?

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

Best regards

Stefan S.

On 9/30/2010 2:15 PM, Stefan S. wrote:

if already_defined(this_method)
  puts 'We are overwriting an existing method by accident'
  Process.exit
end

end
end

This should do the trick:

class String
unless method_defined?(:my_method) then
def my_method
end
else
puts ‘We tried to overwrite an existing method’
Process.exit
end
end

-Jeremy

Run ruby with the -w flag:

$ ruby -w -e ‘class String; def length; end; end’
-e:1: warning: method redefined; discarding old length

I’m not sure if there’s a way to make these warnings fatal.

On Thu, Sep 30, 2010 at 2:53 PM, Alex S. [email protected] wrote:

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

Child1.ruby!( :abc )
puts
Child2.ruby!( ‘abc’ )
puts
Child3.ruby!( /abc/ )

Josh C. wrote:

But is there a way to call the original method instead of just quitting
out?

The super keyword does this

No it doesn’t; not if you redefine a method in the same class.

You need to use alias.

class String
alias :orig_length :length
def length
puts “Whee!”
orig_length
end
end
puts “abc”.length

But is there a way to call the original method instead of just quitting
out?

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”.

On 9/30/2010 2:53 PM, Alex S. wrote:

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.

-Jeremy

On Thu, Sep 30, 2010 at 4:06 PM, Brian C. [email protected]
wrote:

class String

Whoops. Thanks, my brain swapped override and overwrite.

Alex S. wrote:

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.

class Foo
p self
end
Foo
=> nil

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.

Jesus.

Jesús Gabriel y Galán wrote:

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.

On Fri, Oct 1, 2010 at 12:00 PM, Brian C. [email protected]
wrote:

Jesús Gabriel y Galán wrote:

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.