class_eval() problem

7

7stud --

Here is some code that works as expected:

def create_class
Class.new
end

MyClass = create_class

MyClass.class_eval do
def greet
puts 'hi'
end
end

obj = MyClass.new
obj.greet

--output:--
hi


Now here is a more complex version:

def create_class
cl = Class.new

cl.class_eval do
yield
end

return cl
end


MyClass = create_class do

def greet
puts 'hello'
end

end


obj = MyClass.new
obj.send:)greet)
#obj.greet #private method -- NoMethodError


Why is greet() a private method?
 
G

Gunther Diemant

[Note: parts of this message were removed to make it a legal post.]

The greet method is a private method of Object not of MyClass.
So it seems that the def in the block is evaluated in the toplevel scope
(where the block is defined) and not in the MyClass scope.
 
7

7stud --

Gunther Diemant wrote in post #986869:
The greet method is a private method of Object not of MyClass.

Thanks. I didn't realize that Object#methods() returned only public
methods.

So it seems that the def in the block is evaluated in the toplevel scope
(where the block is defined) and not in the MyClass scope.

This is what I've come up with:


def create_class
cl = Class.new

cl.class_eval do

#In this block self=cl because that is
#what class_eval() does

yield #However, the block being yielded to
#doesn't care what the bindings are
#in this block--the block being yielded
#to got its bindings when the block was
#created. (bindings = variable_name/value pairs)

end

return cl
end


#self = main

MyClass = create_class do

#This block takes the bindings present when it was
#created along with it no matter where the block ends up,
#and in the current binding self=main. Remember
#blocks can see the variable bindings present outside the
#block.


def greet
puts 'hello'
end

end


obj = MyClass.new
obj.send:)greet) #hello


The block isn't executed until the yield, and when yield is finally
called the block sees self=main. def statements create instance methods
in the "current class", and when self is not a class, the current class
ends up being the class of self. Because self=main the current class
for the block is main's class, which is Object, so the def becomes in
instance method of Object. In other words, when that block executes
it's the exact same thing as defining a method in the top-level, and by
ruby dictate top-level methods are private methods of Object.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,197
Latest member
Sean29G025

Latest Threads

Top