In this example from The Ruby Programming Language (p.270), I’m confused why the instance_eval method on the last line of the sample code defines a class method called String.empty.
Don’t you use class_eval to define a class method and instance_eval when you want to define an instance method?
o.instance_eval("@x") # Return the value of o's instance variable @x
# Define an instance method len of String to return string length
String.class_eval("def len; size; end")
# Here's another way to do that
# The quoted code behaves just as if it was inside "class String" and "end"
String.class_eval("alias len size")
# Use instance_eval to define class method String.empty
# Note that quotes within quotes get a little tricky...
String.instance_eval("def empty; ''; end")
Unfortunately, it is not as straightforward as that.
First take a closer look at what the examples of
class_evalare doing.class_evalis a method which comes from Ruby’s module class so can be called on any class or module. When you useString.class_evalyou are evaluating the given code in the context of the class. i.e. when you writeString.class_eval("def len; size; end")it’s exactly like you reopened the class and typed the code passed toclass_evale.g.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:instance_evalis 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 Stringstrand say:Then this will alias
specialtosizejust forstrbut not for any other String object: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 useString.instance_evalyou are evaluating the given code in the context of theStringinstance object. i.e. it is equivalent to reopening String’s metaclass and typing the code passed e.g.