Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How and why does this dynamic method definition work?

How does following code works and, more importantly, why does it work that way?

class Example
  def one
    def one
      @value = 99
    end
    puts "Expensive Call"
    @value = 99 # assume its expensive call
  end
end

ex = Example.new
puts ex.one # => "Expensive Call"; 99
puts ex.one # => 99

Here, on first call to method one, Ruby executes the outer one method, but on successive calls, it executes only the inner one method, bypassing the outer one method totally.

I want to know how does it happen and why does it happen so.

like image 731
shailesh Avatar asked Jul 08 '12 16:07

shailesh


People also ask

How do you define and execute a dynamic method?

To define and execute a dynamic method Declare a delegate type to execute the method. Create an array that specifies the parameter types for the dynamic method. Create a DynamicMethod. Emit the method body. Create an instance of the delegate (declared in step 1) that represents the dynamic method by calling the CreateDelegate method.

What is the difference between dynamic method and static method?

The method is associated with the module that contains the Example class, which contains the example code. Any loaded module could be specified. The dynamic method acts like a module-level static method ( Shared in Visual Basic). Emit the method body. In this example, an ILGenerator object is used to emit the Microsoft intermediate language (MSIL).

What is the return type of the dynamic method?

However, the ' name appears in calls stacks and can be useful for ' debugging. ' ' In this example the return type of the dynamic method ' is Long. The method is associated with the module that ' contains the Example class. Any loaded module could be ' specified. The dynamic method is like a module-level ' Shared method.

What are the parameters of the second dynamic method?

The second dynamic method has two parameters, of type Example and type int ( Integer in Visual Basic). When the dynamic method has been created, it is bound to an instance of Example, using a generic delegate that has one argument of type int.


1 Answers

How It Works

Ruby allows you to redefine classes at run-time, because class and def are actually executable code. In your example, the code does the following:

  1. Defines an Example#one method that will (re)define the Example#one method when the instance method is called.
  2. For practical purposes, the inner def will not be executed until the outer instance method is called. (Hair-splitters may legitimately argue this definition, but that gets into details of the parser/interpreter that just don't matter for the purposes of this discussion.)
  3. You define an instance of Example named "ex."
  4. You invoke the instance method on ex, which defines a new method with the same name.
  5. When you call the instance method again, the new method is used instead of the old one.

Why It Works

Basically, the last definition of a method replaces any earlier definitions in that namespace, but the methods are actually new objects. You can see this in action as follows:

def my_method
  puts 'Old Method'
  puts  self.method(:my_method).object_id
  def my_method
    puts 'New Method'
    puts  self.method(:my_method).object_id
  end  
end

If you run this in an irb or pry session, you can see the method redefined at run-time:

> my_method; puts; my_method
Old Method
8998420

New Method
8998360

As you can see by the different object IDs, even though the methods have the same name and are attached to the same object (generally main at the console), they are actually different method objects. However, since the methods were defined with the same name, only the most recent definition is found when the instance does a method lookup.

like image 93
Todd A. Jacobs Avatar answered Oct 06 '22 13:10

Todd A. Jacobs