Is there an alias_method for a class method?
The important thing to understand is that there is no such thing as a class method in Ruby.
A class method is really just a singleton method. There is nothing special about class methods. Every object can have singleton methods. We just call them "class methods" when the object is a Class
because "singleton method of an instance of Class
" is too long and unwieldy.
Wait! Did I say "singleton method"?
Another important thing to understand is that there is no such thing as a singleton method in Ruby.
A singleton method is really just a regular boring old instance method of the singleton class. There is nothing special about singleton methods. They are just instance methods like any other instance method.
In fact, Ruby has only instance methods. No functions, no constructors, no static methods, no class methods, no module functions, no singleton methods.
The question is not "is this a class method, is this a singleton method", but rather "which module is this method defined in?"
"Singleton methods" are really instance methods defined in the singleton class. The syntax for accessing the singleton class of foo
is
class << foo
end
There is also a method Object#singleton_class
which returns the singleton class of an object.
Why am I so aggressively hammering on about the fact that every method is an instance method and that class methods don't exist? Because it means that Ruby's object model is much simpler than people think it is! After all, in your question, you already show that you know how to alias instance methods, but you say that you don't know how to alias class methods. But, that is wrong! You do know how to alias class methods, because they are just instance methods. If you had been taught this fact properly, you would never have needed to ask this question!
Once you understand that every method is an instance method, and that what we call "singleton methods" are just instance methods of the singleton class, the solution becomes clear:
singleton_class.alias_method :a_new_class_method, :a_class_method
Note: when I wrote above that "there is no such thing as X", what I meant was that "there is no such thing as X in the Ruby language". That does not mean that those concepts don't exist in the Ruby community.
We regularly talk about "singleton methods" and "class methods", simply because it is easier than talking about "instance methods of the singleton class" or "instance methods of the singleton class of an object which happens to be an instance of the Class
class". There are even methods like Object#define_singleton_method
, Object#singleton_method
, Object#singleton_methods
, Module#private_class_method
, Module#public_class_method
, and Module#module_function
in the Ruby core library. But it is always important to remember that those are not language concepts. Those are community concepts that only exist in our heads and in the names of some library methods.
alias_method
aliases an instances method of the receiver. Class methods are actually instance methods defined on the singleton class of a class.
class MyClass
def self.a
"Hello World!"
end
end
method_1 = MyClass.method(:a).unbind
method_2 = MyClass.singleton_class.instance_method(:a)
method_1 == method_2
#=> true
To alias an instance method defined on the singleton class you can either open it up using the class << object
syntax.
class << MyClass
alias_method :b, :a
end
MyClass.b
#=> "Hello World!"
Or you can refer to it directly using the singleton_class
method.
MyClass.singleton_class.alias_method :c, :a
MyClass.c
#=> "Hello World!"
If you are still within the class context self
will refer to the class. So the above could also be written as:
class MyClass
class << self
def a
"Hello World!"
end
alias_method :b, :a
end
end
Or
class MyClass
def self.a
"Hello World!"
end
singleton_class.alias_method :c, :a
end
Or a combination of the two.
You can wrap class methods and their alias_method
calls into a separate module and incorporate that module into your class via extend
:
class Foo
def an_inst_method
'instance method'
end
alias_method :a_new_inst_method, :an_inst_method
module ClassMethods
def a_class_method
'class method'
end
alias_method :a_new_class_method, :a_class_method
end
extend ClassMethods
end