Removing Instance Methods

Hello,

How can I remove a method from an instance?

For example, I set a method by doing:

···

#----------
a = 'one'
def a.one
  1
end
#----------

Now how would I undefine a.one?

undef a.one
give a syntax error.

Thank you,
Brian Takita

Brian Takita wrote:

Hello,

How can I remove a method from an instance?

For example, I set a method by doing:

#----------
a = 'one'
def a.one
  1
end
#----------

Now how would I undefine a.one?

class << a
  remove_method :one
end

Hi,

Brian Takita a écrit :

Hello,

How can I remove a method from an instance?

For example, I set a method by doing:

#----------
a = 'one'
def a.one
  1
end
#----------

Now how would I undefine a.one?

undef a.one
give a syntax error.

Thank you,
Brian Takita

You can do something like:

class <<a
   remove_method(:one)
end

But maybe there's a simpler way to do this...

HTH

Ghislain

But maybe there's a simpler way to do this...

Is there? It seems like there should be a way to do this without
resorting to an eval statement?

How does Ruby itself remove methods when parsing remove_method?

Brian Takita wrote:

> But maybe there's a simpler way to do this...
Is there? It seems like there should be a way to do this without
resorting to an eval statement?

The code snippets offered don't use eval. They open the object's
singleton class and remove the method. There isn't really any more
straightforward way (since that is exactly what you want to do). If you
want to do it more concisely, you could add a remove_method to Object
that does this internally.

How does Ruby itself remove methods when parsing remove_method?

Looking at eval.c, it looks like it just deletes the method from the
class' method table.

I'm sorry about the nonexistant explanation.

In this situation, the only solution that I know of is to use an eval.

def custom_remove_method(object, symbol)
  remove_method_script = %-
  class << object
    remove_method(:#{symbol.to_s})
  end

···

-
  eval remove_method_script
end

Looking at eval.c, it looks like it just deletes the method from the class' method table.

Can this be done in Ruby?

Thank you,
Brian Takita

Like this,

def custom_remove_method(object, symbol)
       class << object
               remove_method(symbol.to_sym)
       end
end

···

On 7/19/05, Brian Takita <brian.takita@gmail.com> wrote:

def custom_remove_method(object, symbol)
        remove_method_script = %-
        class << object
                remove_method(:#{symbol.to_s})
        end
        -
        eval remove_method_script
end

I get the following error when running this:

in `custom_remove_method': undefined local variable or method `symbol' for #<Class:#<String:0x27b7bb0>> (NameError)

Unfortunately, I can't figure out how to get the block to recognize the
symbol variable in the method.
I tried this:

def custom_remove_method(obj, sym)
  obj.instance_variable_set(:@symbol_to_be_removed, obj)
  class << obj
    remove_method(@symbol_to_be_removed)
    remove_instance_variable(:@symbol_to_be_removed)
  end
end

but got this error:

warning: instance variable @symbol_to_be_removed not initialized
in `remove_method': nil is not a symbol (TypeError)

at the remove_method(@symbol_to_be_removed) statement.

Even if this hack works, it can possibly cause name clashes at some
level and won't work in a multithreaded environment.

Is there a better approach to getting the class block to recognize the
variable from the outside?

def custom_remove_method(obj, sym)
  obj.instance_variable_set(:@symbol_to_be_removed, obj)
  class << obj
    remove_method(@symbol_to_be_removed)
    remove_instance_variable(:@symbol_to_be_removed)
  end
end

moulon% cat b.rb
#!/usr/bin/ruby
def custom_remove_method(obj, sym)
   class << obj; self end.send(:remove_method, sym)
end
class << a =
   def un
      puts 1
   end
end
a.un
custom_remove_method(a, :un)
a.un
moulon%

moulon% ./b.rb
1
./b.rb:12: undefined method `un' for :Array (NoMethodError)
moulon%

Guy Decoux

Yeah, you're right. I should have tested it first before posting :slight_smile:

Kent.

···

On 7/19/05, ts <decoux@moulon.inra.fr> wrote:

> def custom_remove_method(obj, sym)
> obj.instance_variable_set(:@symbol_to_be_removed, obj)
> class << obj
> remove_method(@symbol_to_be_removed)
> remove_instance_variable(:@symbol_to_be_removed)
> end
> end

moulon% cat b.rb
#!/usr/bin/ruby
def custom_remove_method(obj, sym)
   class << obj; self end.send(:remove_method, sym)
end
class << a =
   def un
      puts 1
   end
end
a.un
custom_remove_method(a, :un)
a.un
moulon%

moulon% ./b.rb
1
./b.rb:12: undefined method `un' for :Array (NoMethodError)
moulon%

Guy Decoux

Thats works, and its a one-liner :slight_smile:

Thank you.

This is a good way to get rid of those pesky 'method redefined'
warnings in cases such as in this case:

def a_method(obj)
  def obj.one
    'one'
  end
end

def a_method2(obj)
  def obj.one
    1
  end
end

one = 'one'
a_method(one)
a_method2(one)

···

warning: redefine one

###########
def custom_remove_method(obj, sym)
  class << obj; self end.send(:remove_method, sym)
end

def a_method(obj)
  custom_remove_method(obj, :one) if obj.respond_to?(:one)
  def obj.one
    'one'
  end
end

def a_method2(obj)
  custom_remove_method(obj, :one) if obj.respond_to?(:one)
  def obj.one
    1
  end
end

one = 'one'
a_method(one)
a_method2(one)