Don't you use class_eval
to define a
class method and instance_eval
when
you want to define an instance method?
Unfortunately, it is not as straightforward as that.
First take a closer look at what the examples of class_eval
are doing. class_eval
is a method which comes from Ruby's module class so can be called on any class or module. When you use String.class_eval
you are evaluating the given code in the context of the class. i.e. when you write String.class_eval("def len; size; end")
it's exactly like you reopened the class and typed the code passed to class_eval
e.g.
class String
def len
size
end
end
Thus to add a class method using class_eval you would write String.class_eval("def self.empty; ''; end")
which has the same effect as:
class String
def self.empty
''
end
end
instance_eval
is defined in Ruby's Object class so is available on any Ruby object. In the general case it can be used to add a method to a specific instance. e.g. if we have a String str
and say:
str.instance_eval("def special; size; end")
Then this will alias special
to size
just for str
but not for any other String object:
irb(main):019:0> "other".special
NoMethodError: undefined method `special' for "other":String
from (irb):19
To understand what is going on with String.instance_eval remember that the class String is itself an object (an instance of the class Class
) and that there is such a singleton instance object of every class defined. When you use String.instance_eval
you are evaluating the given code in the context of the String
instance object. i.e. it is equivalent to reopening String's metaclass and typing the code passed e.g.
class String
class << self
def empty
''
end
end
end