define_method
March 23rd, 2008
While we were waiting for March 20th RubyJax meeting to get started, Steve Bristol entertained us with a Ruby quiz. One of the questions was particularly interesting as it had many possible answers. I will paraphrase the question as:
“How many ways are there to add a method to an existing class in Ruby?”
I have cataloged the answers that were tossed out as well as a few I just added.
1 . Open the class and add a new method
class String
def method_one
puts 'method 1'
end
end
"abcde".method_one
2 . Create a singleton method on an instance
s = "12345"
def s.method_two
puts 'method 2'
end
s.method_two
3 . Use Kernel#method_missing
class String
def method_missing(name, *args)
super unless name == :method_three
puts 'method 3'
end
end
"abcde".method_three
4 . Use Module#define_method
class String
def create_method(name, &block)
self.class.send(:define_method, name, block)
end
end
"abcde".create_method(:method_four) { puts 'method 4' }
"12345".method_four
5 . A variation of #1 : include a module in the class
module ExtraMethods
def method_five
puts 'method 5'
end
end
class String
include ExtraMethods
end
"abcde".method_five
6 . A variation of #4 : use Object#instance_eval
String.instance_eval("define_method(:method_six) { puts 'method 6' }")
"abcde".method_six
7 . We could use Kernel#eval to execute any of the above as well; here we will emulate instance_eval with a binding
class String
def self.get_binding
binding
end
end
eval("define_method(:method_seven) { puts 'method 7' }", String.get_binding)
"abcde".method_seven
Any others?
Leave a Reply