Ruby's Class class lists two methods named 'new':
Class::new is a public class method
Class#new is a public instance method
But when I do:
Class.methods(false)
#=> []
which is supposed to list singleton methods (which I am assuming what class methods are), I get an empty array. Why is this so? Where is Class::new defined?
The methods shown as ::new in the documentation are usually #initialize, for example Range::new:
new(begin, end, exclude_end=false) → rng
Constructs a range using the given begin and end. If the exclude_end parameter is omitted or is false, the rng will include the end object; otherwise, it will be excluded.
This is because you create instances via:
r = Range.new(0, 2) #=> 0..2
Rather than:
r = Range.allocate #=> nil..nil
r.send(:initialize, 0, 2) #=> nil
r #=> 0..2
That's exactly what ::new does – it creates a new instance via allocate, sends it initialize (passing arguments) and returns the instance.
The actual new method is inherited from Class (since Range is an instance of Class) – Class#new:
new(args, ...) → obj
Calls allocate to create a new object of class’s class, then invokes that object’s initialize method, passing it args. This is the method that ends up getting called whenever an object is constructed using .new.
Just like allocate, inherited and superclass (and the instance methods from Class' ancestors like Module as well):
Range.method(:new)
#=> #<Method: Class#new>
Range.method(:allocate)
#=> #<Method: Class#allocate>
Range.method(:ancestors)
#=> #<Method: Class(Module)#ancestors>
So if you call Class.new:
my_string_class = Class.new(String)
#=> #<Class:0x007fdf5485b200>
you just invoke Class#new which is (again) equivalent to:
my_string_class = Class.allocate
my_string_class.send(:initialize, String)
my_string_class
#=> #<Class:0x007fdf5484beb8>
One notable exception is Struct which in fact provide its own new class method:
Struct.method(:new)
#=> #<Method: Struct.new>
Unlike other classes, Struct::new does not return instances of Struct but instances of Class (which are subclasses of Struct).
tl;dr summary:
Why is this so?
Because it's not a singleton method.
Where is Class::new defined?
It isn't. The call Class.new is just calling Class#new (since Class is an instance of itself). The documentation for Foo::new is actually the documentation for Foo#initialize for any class Foo, including Class itself.
If you want to know something about Ruby, it is often a good idea to ask her herself:
new_method = Class.method(:new)
#=> #<Method: Class#new (defined in Class at core/alpha.rb:90)>
The Object#method method returns a Method object representing the method. (Methods aren't objects in Ruby themselves, but you can get a reflective proxy object that represents a method.)
You can ask a Method where it is defined using the Method#owner method:
new_method.owner
#=> Class
As you can see, new is defined in Class and not in Class's singleton class.
You can also ask a Method about the location of its Ruby source code using the Method#source_location method:
new_method.source_location
#=> ['core/alpha.rb', 90]
What this tells us is that Class#new is defined in the file core/alpha.rb on line 90:
def new(*args)
obj = allocate()
Rubinius.asm(args, obj) do |args, obj|
run obj
run args
push_block
send_with_splat :initialize, 0, true
# no pop here, as .asm blocks imply a pop as they're not
# allowed to leak a stack value
end
obj
end
The method is partially implemented in bytecode for performance reasons, but it is basically just:
class Class
def new(*args, &block)
obj = allocate
obj.__send__(:initialize, *args, &block) # because initialize is private
#obj.initialize(*args, &block)
obj
end
end
Now, you might ask yourself: why is there an entry for Class::new in the RDoc documentation, if that method doesn't exist? Well, RDoc knows about the relationship between #initialize which is the method you define but usually don't call directly and Class#new which is the method you call but usually don't define, and it will document #initialize as ::new if it exists.
So, what we really want to look at, is Class#initialize:
initialize_method = Class.method(:initialize)
#=> #<Method: Class#initialize (defined in Class at core/class.rb:15)>
initialize_method.owner
#=> Class
initialize_method.source_location
#=> ['core/class.rb', 15]
This is the source:
def initialize(sclass=Object, name=nil, under=nil)
raise TypeError, "already initialized class" if #instance_type
raise TypeError, "can't make subclass of Class" if Class.equal?(sclass)
set_superclass sclass
# Things (rails) depend on the fact that a normal class is in the constant
# table and have a name BEFORE inherited is run.
under.const_set name, self if under
if sclass
Rubinius.privately do
sclass.inherited self
end
end
super()
end
private :initialize
Class#initialize essentially does three things:
set the superclass
optionally assign the class to a constant to give it a name
call the Class#inherited hook method of the superclass
If you want to know what the relationships between some of the core classes that magically spring into existence at the beginning are, you can take a look at the initialization code of some Ruby execution engines, e.g.
Rubinius: VM::bootstrap_class in machine/ontology.cpp
JRuby: org.jruby.Ruby.initRoot in core/src/main/java/org/jruby/Ruby.java
IronRuby: the initial classes are generated by a program, the generator is in the directory Src/ClassInitGenerator
MRuby: mrb_init_class in src/class.c
Note: depending on what Ruby implementation you use, obviously the places where those methods are defined and how exactly they are defined may vary.
new is defined as a instance method of Class class, rather than a singleton method:
Class.instance_method :new # => #<UnboundMethod: Class#new>
Tricky to note: Class (object) itself is also an instance of Class (class).
Class.instance_of? Class # => true
Related
This question already has answers here:
Ruby what class gets a method when there is no explicit receiver?
(2 answers)
Closed 7 months ago.
In Ruby every method is assigned to an object (right?). Ruby provides a lot of "built in" methods and gives the ability to the user to create "user defined" methods.
Built in methods are all defined in a class like String, Integer, Array and so on. Built in methods are all invoked placing a dot after an object followed by the method call.
string = "example"
string = string.reverse
However, when I define a method with the syntax
def method_name (args)
#body
end
to which object is this method assigned? And why when I have to call a method that I have defined I don't use the "dot syntax" but I just write its name and pass it some arguments without applying it to an object, like this:
method_name args
In Ruby every method is assigned to an object (right?)
Incorrect. In Ruby, methods are assigned to modules (including classes). When you call a method on an object, Ruby runtime searches for the method along the object's class's ancestor chain (the object's singleton class -> the object's class ->
the superclass -> superclass's superclass -> ... -> BasicObject). If the method is found, it is bound to the object and gets called, otherwise the Ruby runtime searches for a special method called method_missing and bind it to the current object and calls it.
to which object is this method assigned?
It's assigned to the class Object, as a private instance method.
def foo
:foo
end
Object.private_instance_methods.grep(/foo/)
#=> [:foo]
I guess Ruby does this in order to make top-level "functions" look global.
class A
def self.a
foo
end
def a
foo
end
end
A.a #=> :foo
A.new.a #=> :foo
There is top-level object in Ruby -- main
def method_name(args)
# body
end
self
# => main
self.methods.grep(/method_name/)
# => [:method_name]
main is an instance of Object. Any methods defined in main become instance methods of Object
Object.private_instance_methods.grep(/method_name/)
# => [:method_name]
This makes them available everywhere (because all classes are descendants of Object), meaning that we can call the method without a receiver inside classes
For example
def foo
puts "foo"
end
class X
def y
foo
end
end
# will print foo
X.new.y
# will raise private method `foo' called for #<X:0x000055e406a0f060> (NoMethodError)
# to reproduce don't use irb, just usual file
X.new.foo
Read more
I've been reading my textbook, and we have come to classes and the keyword self came up. I've been reading some tutorials on tutorialpoint and have read a bunch of SO questions, but for some reason it just isn't clicking in my head Use of ruby Self, so I decided I would tinker around with some examples
Consider
class Box
# Initialize our class variables
##count = 0
def initialize(w,h)
# assign instance avriables
#width, #height = w, h
##count += 1
end
def self.printCount()
puts "Box count is : ###count"
end
end
# create two object
box1 = Box.new(10, 20)
box2 = Box.new(30, 100)
# call class method to print box count
Box.printCount()
Why will we get an error if we remove self. from our printCount() method? I know that self is important to distinguish between class variables and instance variables like in my example #width,#height and ##count.
So what I think is that since I am trying to modify the class variable ##count, I need to use the .self keyword since I am trying to modify a class variable. Thus whenever we want to change a class variable we must use the form def self.methodName.
Is my thought process correct?
There are two types of methods you are using here: instance methods and class methods. As you know, Ruby is an object oriented programming language, so everything is an object. Each object has its own methods that it can call. Let's look at your code
class Box
# Initialize our class variables
##count = 0
def initialize(w,h)
# assign instance avriables
#width, #height = w, h
##count += 1
end
def self.printCount()
puts "Box count is : ###count"
end
end
When you create a method with self.method_name, you are creating the method for the class itself. So the object of Box has a method called printCount(). That is why you can directly call the method.
Box.printCount()
However, if you declare a new instance of the class Box, calling printCount() would result in an error.
box1 = Box.new(1,1)
box1.printCount() #=> undefined method `printCount'
This is because box1 is an instance of the class Box, and the printCount method is only accessible to the class Box.
If you remove the self before the method printCount, it will become an instance method, and then box1 will have access to that method, but then the class Box will not.
And a few semantics, Ruby uses snake_case for method names, so printCount should be print_count. This is just standard practice, doesn't really affect how the code runs.
Also, you need to be careful with class variables, ie ##count. They don't behave as you would expect in Ruby. It does not just belong in the class it is declared in, it is also part of any of its descendants.
For example, let's say I define a new class call SmallBox and inherit from Box.
box1 = Box.new(1,1)
box1 = Box.new(1,1)
Now, the count should be 2 for Box. However, if you try to access the ##count from my new class,
class SmallBox < Box
p ##count
end
This would print 2 as well.
Any changes to the class variable from the descendants will change its value.
For example, I declare an instance of SmallBox, which would add 1 to ##count. You can see if you check the count in Box, it also added 1.
small1 = SmallBox.new(1,1)
class SmallBox
p ##count #=> 3
end
class Box
p ##count #=> 3
end
I would like to provide a more concrete definition which clarifies the lookup algorithm.
First, let's define self. self in Ruby is a special variable that always references the current object. The current object (self) is the default receiver on method calls. Second, self is where instance variables are found.
class MyClass
def method_one
#var = 'var'
method_two
end
def method_two
puts "#var is #{#var}"
end
end
obj = MyClass.new
obj.method_one
Above, when we call method_one, self will refer to the object instantiated, since we invoked method_one on an explicit receiver (the object instance). so self.method_one in the method definition in the Class will refer to the object instance not the Class object itself. #var will be stored in self. Note that when method_two is called, since there is no default receiver, the receiver is self. So when method_two is called, we remain in the same object instance. That is why #var in method_two will refer to the same #var in method_one. It is the same object.
Ruby supports inheritance. So if we call a method on self and it is not defined in its class, then Ruby will search for the instance method in the superclass. This happens until Ruby gets to BasicObject. If it cannot find the method in any of the superclasses, it raises a NoMethodError.
Now there is another important piece to the inheritance chain. There is an anonymous class called the singleton class that Ruby will inject into this inheritance chain. Where in the inheritance chain? It inserts it right before the original class of the object. This way, when ruby searches for the method, it will hit the singleton class before it hits the original class of the object.
> msg = 'Hello World'
=> "Hello World"
> def msg.hello_downcase
> puts 'Hello World'.downcase
> end
=> :hello_downcase
> msg.downcase
=> "hello world"
> msg2 = 'Goodbye'
=> "Goodbye"
> msg2.hellow_downcase
NoMethodError: undefined method `hellow_downcase' for "Goodbye":String
The lookup algorithm:
msg -> Anonymous Singleton Class (hello_downcase method is in here) -> String -> Object
msg2 -> String -> Object
In the above example, msg and msg2 are both object instances of the String class object. But we only opened up the singleton class of msg and not msg2. the hello_downcase method was inserted into the singleton class of msg. It's important to note that when we add another singleton method, it will reopen the same singleton class again; it will not open another anonymous singleton class. There will only be one anonymous singleton class per instance.
Notice above I said the String class object, and not just the String class. That's because a class itself is an object. A class name is simply a constant which points to an object:
class HelloWorld
def say_hi
puts 'Hello World'
end
end
More precisely, in the above example, HelloWorld is a constant which points to an object, whose class is Class. Because of this, the lookup chain will be different for HelloWorld and its instances. An instance's class is HelloWorld. And when we invoke a method with the instance as the receiver, inside HelloWorld method definitions, self will refer to that instance. Now HelloWorld's class is Class (Since Class.new is what created HelloWorld). And because of this, its inheritance chain looks different:
#<HelloWorld:0x007fa37103df38> -> HelloWorld -> Object
HelloWorld -> Class -> Module -> Object
Now since HelloWorld is also an object, just as with instances, we can open up its Singleton Class.
class HelloWorld
def self.say_hi_from_singleton_class
puts 'Hello World from the Singleton Class'
end
end
HelloWorld.say_hi_from_singleton_class
The lookup algorithm:
HelloWorld -> Anonymous Singleton Class -> Class (this is where the new method is defined) -> Module -> Object
Why does this work? As mentioned, a method call with an explicit receiver changes the value of self to point to that object. The second thing that changes the value of self is a class definition. self inside of the class definition refers to the class object, referred to by constant HelloWorld. This is only the case while inside of the class definition. Once we leave the class definition, self will no longer refer to the constant HelloWorld.
> puts self
main
> class HelloWorld
> puts self
> end
HelloWorld
=> nil
> puts self
main
Ultimately, there are two ways in which the special variable self will change: 1) when you call a method with an explicit receiver, 2) inside of a class definition.
I am reading the Module documentation but can't seem to understand their differences and which should be used where.
How is the eval different than exec?
I'm going to answer a bit more than your question by including instance_{eval|exec} in your question.
All variations of {instance|module|class}_{eval|exec} change the current context, i.e. the value for self:
class Array
p self # prints "Array"
43.instance_eval{ p self } # prints "43"
end
Now for the differences. The eval versions accepts a string or a block, while the exec versions only accept a block but allow you to pass parameters to it:
def example(&block)
42.instance_exec("Hello", &block)
end
example{|mess| p mess, self } # Prints "Hello" then "42"
The eval version does not allow to pass parameters. It provides self as the first parameter, although I can't think of a use for this.
Finally, module_{eval|exec} is the same as the corresponding class_{eval|exec}, but they are slightly different from instance_{eval|exec} as they change what is the current opened class (i.e. what will be affected by def) in different ways:
String.instance_eval{ def foo; end }
Integer.class_eval { def bar; end }
String.method_defined?(:foo) # => false
String.singleton_methods.include?(:foo) # => true
Integer.method_defined?(:bar) # => true
So obj.instance_{eval|exec} opens the singleton class of obj, while mod.{class|module}_{eval|exec} opens mod itself.
Of course, instance_{eval|exec} are available on any Ruby object (including modules), while {class|module}_* are only available on Module (and thus Classes)
To answer your last question first, eval (in all its variations) is completely different from exec. exec $command will start a new process to run the command you specify and then exit when that finishes.
class_eval and module_eval have the power to redefine classes and modules -- even those that you yourself did not write. For example, you might use class eval to add a new method that did not exist.
Fixnum.class_eval { def number; self; end }
7.number # returns '7'
class_eval can be used to add instance methods, and instance_eval can be used to add class methods (yes, that part is very confusing). A class method would be something like Thing.foo -- you're literally calling the foo method on the Thing class. An instance method is like the example above, using class_eval I've added a number method to every instance of Fixnum.
Okay, so that's the *_eval class of methods. The exec methods are similar, but they allow you to look inside a class and execute a block of code as though it was defined as a method on that class. Perhaps you have a class that looks like this:
class Foo
##secret = 'secret key'
##protected = 'some secret value'
def protected(key)
if key == ##secret
return ##protected
end
end
end
The class Foo is just a wrapper around some secret value, if you know the correct key. However, you could trick the class into giving you its secrets by executing a block inside the context of the class like so:
Foo.class_exec { ##secret = 'i'm a hacker' }
Foo.protected('i'm a hacker') #returns the value of ##protected because we overwrote ##secret
In general, with a lot of the tools in ruby, you could use any of these to solve a lot of problems. A lot of the time you probably won't even need to unless you want to monkey patch a class some library you use has defined (although that opens up a whole can of worms). Try playing around with them in irb and see which you find easier. I personally don't use the *_exec methods as much as the *_eval methods, but that's a personal preference of mine.
To avoid ambiguity I'm going to call a method that belongs to (owned by) a singleton class a singleton method. The rest are instance methods. Although one might say that a singleton method of an object is an instance method of its singleton class.
tl;dr Use class_eval/module_eval on a class/module to define instance methods, and instance_eval on a class/module to define class methods (or to be more precise, use instance_eval to define singleton methods). Additionally you can use instance_eval to access instance variables.
A terminology is a bit lacking in this case. ruby maintains a stack of class references (cref for short). When you open/reopen a class, the corresponding class reference is pushed to the stack. And the current class refernece affects where def defines methods (to which class/module they're added).
Now, class_eval/module_eval and class_exec/module_exec are aliases.
The *_exec() variants don't accept strings, and allow to pass arguments to the block. Since the *_eval() variants are mainly used I'll focus on them.
class_eval/module_eval changes cref and self to the receiver (Thing in Thing.module_eval(...)):
rb_mod_module_eval() -> specific_eval()
yield_under() (for blocks)
vm_cref_push()
eval_under() (for strings)
vm_cref_push()
instance_eval changes cref to the singleton class of the receiver, and self to the receiver.
Let's see them in action:
class A
p self #=> A
#a = 1
def initialize
#b = 2
end
end
p A.instance_variables #=> [:#a]
p A.new.instance_variables #=> [:#b]
#a on a class level adds an instance variable to the class A as an object. I'm adding it here for completeness. But that's not how you add a class variable.
A.instance_eval do
p self #=> A
p #a #=> 1
def m() puts 'm' end
end
sclass = A.singleton_class
p sclass.instance_methods(false).include? :m #=> true
A.m #=> m
a = A.new
a.instance_eval do
p self #=> #<A:0x00007fc497661be8 #b=2>
p #b #=> 2
def m2() puts 'm2' end
end
sclass = a.singleton_class
p sclass.instance_methods(false).include? :m2 #=> true
a.m2 #=> m2
So, inside instance_eval def adds a singleton method to the receiver (an instance method to the singleton class of the receiver). For a class/module that means a class/module method. For other objects, a method that is available for that particular object.
A.class_eval do
p self #=> A
p #a #=> 1
def m() puts 'm' end
end
p A.instance_methods(false).include? :m #=> true
A.new.m #=> m
And, inside class_eval def adds an instance method to the receiver itself (the class/module). class_eval is only available for classes/modules.
Also, when class_eval is passed a block, constant/class variable lookup is not affected:
module A
C = 1
##c = 1
class B
C = 2
##c = 2
end
A::B.class_eval { p [C, ##c] } #=> [1, 1]
A::B.class_eval 'p [C, ##c]' #=> [2, 2]
end
The naming is confusing. I might guess that instance in instance_eval suggests that receiver is treated as an instance (allows to change things for a particular instance), and class in class_eval as a class (allows to change things for a class of objects).
I'm stuck. I'm trying to dynamically define a class method and I can't wrap my head around the ruby metaclass model. Consider the following class:
class Example
def self.meta; (class << self; self; end); end
def self.class_instance; self; end
end
Example.class_instance.class # => Class
Example.meta.class # => Class
Example.class_instance == Example # => true
Example.class_instance == Example.meta # => false
Obviously both methods return an instance of Class. But these two instances
are not the same. They also have different ancestors:
Example.meta.ancestors # => [Class, Module, Object, Kernel]
Example.class_instance.ancestors # => [Example, Object, Kernel]
What's the point in making a difference between the metaclass and the class instance?
I figured out, that I can send :define_method to the metaclass to dynamically define a method, but if I try to send it to the class instance it won't work. At least I could solve my problem, but I still want to understand why it is working this way.
Update Mar 15, 2010 13:40
Are the following assumptions correct.
If I have an instance method which calls self.instance_eval and defines a method, it will only affect the particular instance of that class.
If I have an instance method which calls self.class.instance_eval (which would be the same as calling class_eval) and defines a method it will affect all instances of that particular class resulting in a new instance method.
If I have a class method which calls instance_eval and defines a method it will result in a new instance method for all instances.
If I have a class method which calls instance_eval on the meta/eigen class and defines a method it will result in a class method.
I think it starts to make sense to me. It would certainly limit your possibilities if self inside an class method would point to the eigen class. If so it would not be possible to define an instance method from inside a class method. Is that correct?
Defining a singleton method dynamically is simple when you use instance_eval:
Example.instance_eval{ def square(n); n*n; end }
Example.square(2) #=> 4
# you can pass instance_eval a string as well.
Example.instance_eval "def multiply(x,y); x*y; end"
Example.multiply(3,9) #=> 27
As for the difference above, you are confusing 2 things:
The meta class defined by you, is what called in Ruby community as singelton class or eigen class. That singleton class is the class that you can add class(singleton) methods to.
As for the class instance you are trying to define using the class_instance method, is nothing but the class itself, to prove it, just try adding an instance method to the class Example and check if the class_instance method defined by you returns the class Example itself by checking the existence of that method:
class Example
def self.meta; (class << self; self; end); end
def self.class_instance; self; end
def hey; puts hey; end
end
Example.class_instance.instance_methods(false) #=> ['hey']
Anyway to sum it for you, when you want to add class methods, just add them to that meta class. As for the class_instance method is useless, just remove it.
Anyway I suggest you read this post to grasp some concepts of Ruby reflection system.
UPDATE
I suggest you read this nice post: Fun with Ruby's instance_eval and class_eval,
Unfortunately class_eval and instance_eval are confusing because they somehow work against their naming!
Use ClassName.instance_eval to define class methods.
Use ClassName.class_eval to define instance methods.
Now answering your assumptions:
If I have an instance method which
calls self.instance_eval and defines a
method, it will only affect the
particular instance of that class.
yes:
class Foo
def assumption1()
self.instance_eval("def test_assumption_1; puts 'works'; end")
end
end
f1 = Foo.new
f1.assumption1
f1.methods(false) #=> ["test_assumption_1"]
f2 = Foo.new.methods(false) #=> []
If I have an instance method which
calls self.class.instance_eval (which
would be the same as calling
class_eval) and defines a method it
will affect all instances of that
particular class resulting in a new
instance method.
no instance_eval in that context will define singleton methods(not instance ones) on the class itself:
class Foo
def assumption2()
self.class.instance_eval("def test_assumption_2; puts 'works'; end")
end
end
f3 = Foo.new
f3.assumption2
f3.methods(false) #=> []
Foo.singleton_methods(false) #=> ["test_assumption_2"]
For that to work replace instance_eval with class_eval above.
If I have a class method which calls
instance_eval and defines a method it
will result in a new instance method
for all instances.
Nope:
class Foo
instance_eval do
def assumption3()
puts 'works'
end
end
end
Foo.instance_methods(false) #=> []
Foo.singleton_methods(false) #=> ["assumption_3"]
That will make singleton methods, not instance methods. For that to work replace instance_eval with class_eval above.
If I have a class method which calls
instance_eval on the meta/eigen class
and defines a method it will result in
a class method.
well no, that will make so sophisticated stuff, as it will add singleton method to the singleton class, I don't think that will have any practical use.
If you define a method on a class, it can be invoked on its objects. It is an instance method.
class Example
end
Example.send :define_method, :foo do
puts "foo"
end
Example.new.foo
#=> "foo"
If you define a method on a metaclass, it can be invoked on the class. This is similar to the concept of a class method or static method in other languages.
class Example
def self.metaclass
class << self
self
end
end
end
Example.metaclass.send :define_method, :bar do
puts "bar"
end
Example.bar
#=> "bar"
The reason that metaclasses exist is because you can do this in Ruby:
str = "hello"
class << str
def output
puts self
end
end
str.output
#=> "hello"
"hi".output
# NoMethodError
As you can see, we defined a method that is only available to one instance of a String. The thing that we defined this method on is called the metaclass. In the method lookup chain, the metaclass is accessed first before searching the object's class.
If we replace the object of type String with an object of type Class, you can imagine why this means we're only defining a method on a specific class, not on all classes.
The differences between the current context and self are subtle, you can read more if you're interested.
Foo = Class.new
Foo.instance_eval do
def instance_bar
"instance_bar"
end
end
puts Foo.instance_bar #=> "instance_bar"
puts Foo.new.instance_bar #=> undefined method ‘instance_bar’
My understanding is that calling instance_eval on an object is supposed to allow you to define an instance variable or method for that object.
But in the example above, when you call it on class Foo to define the instance_bar method, instance_bar becomes a class method that can be invoked with "Foo.instance_bar". It is clear that this code has not created an instance method because Foo.new.instance_bar results in "undefined method ‘instance_bar’".
Why does instance_eval define a class method rather than an instance method in this context?
x.instance_eval changes your context so self evaluates to x.
This allows you to do many things, including defining instance variables and instance methods but only for x.
x = Object.new
y = Object.new
# define instance variables for x and y
x.instance_eval { #var = 1 }
y.instance_eval { #var = 2 }
# define an instance method for all Objects
class Object
def var
#var
end
end
x.var #=> 1
y.var #=> 2
Ruby lets you define instance methods for an object in a couple places. Normally,
one defines them in a class, and those instance methods are shared among all instances
of that class (like def var above).
However, we can also define an instance method for just a single object:
# here's one way to do it
def x.foo
"foo!"
end
# here's another
x.instance_eval do
# remember, in here self is x, so bar is attached to x.
def bar
"bar!"
end
end
Even though x and y have the same class, they don't share these methods, since they were only defined for x.
x.foo #=> "foo!"
x.bar #=> "bar!"
y.foo #=> raises NoMethodError
y.bar #=> raises NoMethodError
Now in ruby, everything's an object, even classes. Class methods are just instance methods
for that class object.
# we have two ways of creating a class:
class A
end
# the former is just syntatic sugar for the latter
B = Class.new
# we have do ways of defining class methods:
# the first two are the same as for any other object
def A.baz
"baz!"
end
A.instance_eval do
def frog
"frog!"
end
end
# the others are in the class context, which is slightly different
class A
def self.marco
"polo!"
end
# since A == self in here, this is the same as the last one.
def A.red_light
"green light!"
end
# unlike instance_eval, class context is special in that methods that
# aren't attached to a specific object are taken as instance methods for instances
# of the class
def example
"I'm an instance of A, not A itself"
end
end
# class_eval opens up the class context in the same way
A.class_eval do
def self.telegram
"not a land shark"
end
end
Note again, that all these methods are A-specific, B doesn't get access to any of them:
A.baz #=> "baz!"
B.telegram #=> raises NoMethodError
The important thing to take away from here is that
class methods are just instance methods of an object of class Class
The purpose of 'instance_eval' is to extend objects, but the purpose of 'class_eval' is to extend classes. And because classes are also objects, you can apply instance_eval on classes.
I guess that extending of classes is just more understandable in classic OOP. Dynamic languages allow us to easily specify behaviour of particular objects. Fact that each object can have own behaviour adds a lot of flexibility designing an application. Not only data can vary for objects of the same class. Two humans differ not only because they were born in different years, not only because they have different parents but they can think different and thus behave different.
Ability to change the behaviour of each object is fundamental. It exists in many languages.
Thinking about instance_eval think about objects first. Then you'll realize that classes are also objects - objects which additional purpose to create new objects, to hold description of common behaviour (methods). You can not only use definition of a class, but can also assign class to a variable, pass class as an argument, call method on a class, program a class!
I would recommend articles written by Yehuda Katz and Yugui to dive deeper into it:
http://yehudakatz.com/2009/11/15/metaprogramming-in-ruby-its-all-about-the-self/
http://yugui.jp/articles/846