Why does Kernel define class_eval?

First, I'd like to say it makes sense to define instance_eval in BasicObject. Both object instances (e.g. obj = Object.new or obj = MyClass.new) and class objects (e.g. MyClass = Class.new) are both instances of a class, in the former of the class Object or a client- defined class (which implicitly inherits from Object) and in the latter of the class Class. But because they are both instances, we want to give them both access to the method instance_eval. It makes sense to define this method instance_eval in either Object or BasicObject, so that they will be inherited by regular object instances and class objects.

class_eval is justifiably declared in the Module class. class_eval evaluates a class and adds instance methods to that class. All class objects are instances of Class, and Module is the superclass of Class. Hence, all class objects have access to the instance methods of Module, where class_eval is defined, in addition to them having access to the instance methods of class Class. For example:

1.9.3p0 :092 > MyClass.class_eval { 1.9.3p0 :093 > def my_class 1.9.3p0 :094?> puts "yes im an instance method of #{self.class.name}" 1.9.3p0 :095?> end 1.9.3p0 :096?> } => nil 1.9.3p0 :097 > MyClass.new.my_class yes im an instance method of MyClass

Basically, what we did with class_eval is evaluate the class context to add methods to it for the class' instances. So it really would not make sense to have a class_eval definition available to instances themselves. Yet, in the current library, it's possible:

1.9.3p0 :098 > obj = Object.new => #<Object:0x007ff4ec8fc0f8> 1.9.3p0 :099 > obj.class_eval {} => nil

What's written above really doesn't make any sense, but it works. There's no NoMethodError exception raised when invoking class_eval on the object instance. In actuality, that class_eval invocation does not trace to Module's definition of class_eval. That would be impossible, because obj is an instance of Object class, which inherits from BasicObject and the inheritance chain stops there. There's no Module in obj's inheritance chain. So then where is class_eval defined for obj? It's defined in Kernel:

1.9.3p0 :083 > Kernel.instance_methods(false).include? :class_eval => true

As you may know, the Kernel module is included in Object and hence all its method definitions become available as instance methods to Object, so that when our obj instance invokes class_eval, it will first search Object class, and then check the module Kernel, where the definition will be found.

But I don't see why class_eval is defined in Object. The obj instance is not a class object, and therefore the new method is not available to it, so it's not like we can add instance methods to obj within the block of class_eval:

1.9.3p0 :098 > obj = Object.new => #<Object:0x007ff4ec8fc0f8> 1.9.3p0 :101 > obj.class_eval { 1.9.3p0 :102 > def my_class 1.9.3p0 :103?> puts "yes im an instance method of #{self.class.name}" 1.9.3p0 :104?> end 1.9.3p0 :105?> } => nil 1.9.3p0 :106 > obj.new.my_class NoMethodError: undefined method `new' for #<Object:0x007ff4ec8fc0f8>

#as expected, the exception is raised, because obj is not a class object.

So why is class_eval in Kernel? obj is not a class object, and we shouldn't be allowed to invoke class_eval on obj...

obj = Object.new obj.class_eval {}

--output:-- 1.rb:2:in `<main>': undefined method `class_eval' for #<Object:0x000001010913f0> (NoMethodError)

puts Kernel.instance_methods(false).include? :class_eval

--output:-- false

$ ruby --version ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-darwin10.8.0]

$ rvm use 1.8.7

$ ruby --version ruby 1.8.7 (2012-06-29 patchlevel 370) [i686-darwin10.8.0]

obj = Object.new obj.class_eval {}

--output:-- 1.rb:2:in `<main>': undefined method `class_eval' for #<Object:0x000001010913f0> (NoMethodError)

puts Kernel.instance_methods(false).include? :class_eval

--output:-- false

This is not a standard ruby method. The Kernel module is being monkeypatched by the activesupport gem.

[13] pry(main)> o=Object.new => #Object:0x000000047102d8 [14] pry(main)> show-method o.class_eval

Number of lines: 3 Owner: Kernel Visibility: public

def class_eval(*args, &block)

singleton_class.class_eval(*args, &block) end [15] pry(main)> o.class_eval { def test; :test; end;} => nil [16] pry(main)> o.test => :test