Metaprogramming: Where does method dispatch look when we call an instance method that is defined inside a class method?

StackOverflow https://stackoverflow.com/questions/9849231

Question

I'm reading Metaprogramming Ruby and just want to clear something up about the following paraphrased code:

class MyClazz
  def self.my_class_method(name)
    define_method(name) {
      # do stuff
    }
  end

  my_class_method :foo
  my_class_method :bar
end

# The code above generates instance methods:

# def foo
#   do stuff
# end

# def bar
#   do stuff
# end

Q1 My first question regards the two method calls at the end of the file: my_class_method :foo and my_class_method :bar. Am I right in thinking that they are both invoked automatically when a MyClazz object is instantiated?

Q2 When Ruby generates these methods (def foo and def bar), it will put them in MyClazz's eigenclass, even though they are instance methods. So does this mean that Ruby looks to the eigenclass for both class and instance methods when needed?

I just want to clear that up before I move too far into the book.

Was it helpful?

Solution

Answer 1: (short) They are invoked when ruby instantiate MyClass instance (of type Class).

(long) When Ruby interpreter sees a class definition (class MyClazz) it instantiate an instance of this class and evaluate all the code inside class definition.

In your case MyClazz is a constant that holds a refference to the object of class Class. And when Ruby initialize it, it execute code inside class definition - defines singleton method my_class_method of this Class instance and executes method my_class_method twice in the context of this Class instance.

Answer 2: (short) Module#define_method private method adds method to the method table of Class instance (method table holds instance methods of the class). It does not affect eigenclass of istance object/class object.

(long) When you call instance method on the object, Ruby first looks this method in the eigenclass of this object, then in the superclass of eigenclass (it will be a Class object of the object's class). But it will not look in the eigenclass of MyClazz object.

Example:

obj = MyClazz.new
obj.foo # => ok

obj.foo will look for foo method definition in eigenclass of obj object, then will look for instance methods of MyClass (instance of class Class), then in the superclass of MyClass object (in your case this is Object class) etc.

obj = MyClass.new
MyClass.my_class_method :baz
obj.baz # => ok

MyClass.my_class_method will look for my_class_method method definition in the eigenclass of MyClass object (sidenote: eigenclass of a class sometimes is called a metaclass) and it will find it here and will add baz instance method to the class MyClass.

OTHER TIPS

A1: Yes these methods are created upon instantiation.

A2: Russ Olsen does a great job of explaining this in his book Eloquent Ruby. The eigenclass (or singleton class) "sits between every object and its regular class". As such, when Ruby doesn't find the method it's looking for in the instance methods, it will begin traveling up the inheritance tree. The next stop is the eigenclass and from there the class itself.

Olsen also gives an interesting discussion about how all Class methods are actually singleton methods between the new class and the Class object.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top