Difference between alias and alias_method

In the example below, I really can’t sort out why using alias_method
will work, while using alias won’t. Could someone shred me some light
on this? Thanks.

class T
def initialize()
puts “T’s initialize”
end
def self.redefine
alias old_initialize initialize
#alias_method :old_initialize, :initialize
self.module_eval do
define_method :initialize do
old_initialize(1)
end
end
end
end

class S < T
def initialize(int)
puts “S’s initialize:#{int}”
end
redefine()
end
S.new

==========================
Using alias:
in `old_initialize’: wrong number of arguments (1 for 0) (ArgumentError)
(T’s initialize was called)

Using alias_method:
S’s initialize:1
(S’s initialize was called, as expected)

On Dec 17, 12:42 pm, Chan S. [email protected] wrote:

#alias_method :old_initialize, :initialize
puts “S’s initialize:#{int}”
Using alias_method:
S’s initialize:1
(S’s initialize was called, as expected)

Don’t know exactly why, but wrapping alias in a class_eval seems to
fix the problem:

class_eval(“alias old_initialize initialize”)

Using ri, I couldn’t even find who exactly alias belongs to (i.e. is
it defined in Kernel, Object, Module, or what, and is it a class
method of one of these?) Hopefully someone else can weigh in and
clear this up.

Jason

On Dec 17, 12:42 pm, Chan S. [email protected] wrote:

In the example below, I really can’t sort out why using alias_method
will work, while using alias won’t. Could someone shred me some light
on this? Thanks.

I believe it’s a scoping issue. Move the alias statement so that it’s
within the module_eval block as below:

On Dec 17, 11:12 pm, “[email protected][email protected]
wrote:

Don’t know exactly why, but wrapping alias in a class_eval seems to
fix the problem:

class_eval(“alias old_initialize initialize”)

Using ri, I couldn’t even find who exactly alias belongs to (i.e. is
it defined in Kernel, Object, Module, or what, and is it a class
method of one of these?) Hopefully someone else can weigh in and
clear this up.

This is because “alias” is not a method - it’s a keyword (that trips
me up every time I put a comma between the old and new method name,
and the compiler complains).

You can use “alias” in two contexts. You normally use it in a class
definition to alias an instance method of the class. It’s not enough
that the class is “self” - you really must be inside the class
definition. That’s why this works:

MyClass.class_eval{ alias :to_string :to_s }

while this doesn’t (at least, not as you might think):

MyClass.instance_eval{ alias :to_string :to_s }

What happens if you use alias outside a class definition instead?
When you do that, you’re actually aliasing a method of “self” (the
current object) to a singleton method:

irb(main):001:0> c = Object.new
=> #Object:0x2e8f0d8
irb(main):002:0> c.instance_eval { alias :clazz :class }
=> nil
irb(main):003:0> c.clazz
=> Object

(If you don’t know what a “singleton method” is, you can find many
threads about the topic on this group. Be advised that this will
require you to take a journey into Ruby metaprogramming).

As a special case of the above, if “self” is a class, then you’re
aliasing an existing method to a singleton method of the class - and a
singleton method of the class is what we usually call a class method.
That’s why instance_eval() might surprise you:

irb(main):003:0> String.instance_methods[0…1]
=> ["%", “select”]
irb(main):004:0> String.instance_eval { alias :x :instance_methods }
=> nil
irb(main):006:0> String.x[0…1]
=> ["%", “select”]

Bottom line: if you want “alias” to behave as you probably want it to
behave, do like Jason suggested and wrap it in a class_eval(). :slight_smile:

Paolo Perrotta
Bologna, Italy

Agree with Brian. I think the difference is that for alias, how the
method names are resolved depends statically on the context the alias
statement is under, and for alias_method, the symbols are resolved to
methods dynamically:

class T
def self.redefine
alias bar foo
#alias_method :bar, :foo
end
def foo ; puts “T’s foo” ; end
end

class S < T
def foo ; puts “S’s foo” ; end
redefine()
end

S.new.bar
puts T.instance_methods.grep(/bar/)

For alias, bar and foo are resolved to T’s instance methods.
For alias_method, :bar and :foo are resolved to S’s instance methods.

And this is what surprised me. I’m not sure this is by design or by
accident.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs