# Method equality; setting instance variables on Method instan

**URL:** <https://www.ruby-forum.com/t/method-equality-setting-instance-variables-on-method-instan/80355>\
**Category:** Ruby\
**Created:** [December 24, 2006, 6:26pm UTC](https://www.ruby-forum.com/t/method-equality-setting-instance-variables-on-method-instan/80355 "2006-12-24T18:26:14Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![phrogz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/2acd7d/32.png) [@phrogz](https://www.ruby-forum.com/u/phrogz)\
**Post date:** [December 24, 2006, 6:26pm UTC](https://www.ruby-forum.com/t/method-equality-setting-instance-variables-on-method-instan/80355/1 "2006-12-24T18:26:14Z")

</div>

A few questions about the code below:

1. Why do m1 and m2 have different IDs but compare as equal?
2. Why does m2 invoke the same old functionality when run?
3. Why did my instance\_variable\_set not ‘take’?

I suspect all answers have something to do with where the methods are  
being defined/shadowed, but I’ll be damned if I can figure them out.

slim:~/Desktop/test gavinkistner$ ls -Flag  
total 8  
drwxr-xr-x 3 staff 102 Dec 24 10:15 ./  
drwx------ 34 staff 1156 Dec 24 10:15 …/  
-rw-r–r-- 1 staff 734 Dec 24 10:20 override.rb

slim:~/Desktop/test gavinkistner$ cat override.rb  
class Module  
def override( method\_name, &block )  
orig\_method = method( method\_name )  
new\_name = “m#{rand(1000000000)}”  
alias\_method new\_name, method\_name  
define\_method( method\_name, &block )  
method( method\_name ).instance\_variable\_set( :@\_\_orig\_method\_name,  
new\_name )  
end

def restore( method\_name )  
alias\_method method\_name, method( method\_name  
).instance\_variable\_get( :@\_\_orig\_method\_name )  
end  
end

m1 = Kernel.method( :system )  
system ‘ls’

Kernel.override( :system ){ |code| puts "`#{code}` not allowed"}  
m2 = Kernel.method( :system )  
system ‘ls’

p m1, m2, m1==m2, m1.object\_id, m2.object\_id  
m1.call( ‘ls’ )  
m2.call( ‘ls’ )

Kernel.restore( :system )  
m3 = Kernel.method( :system )  
system ‘ls’

**END**

slim:~/Desktop/test gavinkistner$ ruby override.rb  
override.rb  
`ls` not allowed  
#\<Method: Kernel.system\>  
#\<Method: Kernel.system\>  
true  
953400  
953250  
override.rb  
override.rb  
override.rb:11:in `alias_method': nil is not a symbol (TypeError) from override.rb:11:in`restore’  
from override.rb:26

---

<div class="post-metadata">

**Author:** ![phrogz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/2acd7d/32.png) [@phrogz](https://www.ruby-forum.com/u/phrogz)\
**Post date:** [December 24, 2006, 9:26pm UTC](https://www.ruby-forum.com/t/method-equality-setting-instance-variables-on-method-instan/80355/2 "2006-12-24T21:26:32Z")

</div>

Phrogz wrote:

> A few questions about the code below:
> 
> 1. Why do m1 and m2 have different IDs but compare as equal?
> 2. Why does m2 invoke the same old functionality when run?
> 3. Why did my instance\_variable\_set not ‘take’?

Another data point on that last question: at least it looks like you  
can set/get instance variables on a Method instance in general:

irb(main):001:0\> m1 = Kernel.method( :system )  
=\> #\<Method: Kernel.system\>  
irb(main):002:0\> m1.instance\_variable\_set( :@foo, :bar )  
=\> :bar  
irb(main):003:0\> m1.instance\_variables  
=\> ["@foo"]  
irb(main):004:0\> m1.instance\_variable\_get( :@foo )  
=\> :bar

In case it wasn’t obvious, what I am trying to achieve with the above  
code is a stack-like method override/restore system. Each time you  
override a method, the method should store the name of the  
randomly-chosen alias for the old method.

A workaround will be to store the stack of method names on the module  
itself (which I’ll try next); nonetheless, I’m interested in why my  
original code didn’t work as I expected.
