ruby metaprogramming

La definición de Ruby y instance_eval vs. class_eval



metaprogramming (2)

Creo que su confusión proviene del hecho de que la definición no depende del yo actual, podría pensar que es una "clase actual" que tiene sus propias reglas.

Siguiendo tus ejemplos:

class A # defs here go to A puts self # => A class << self #defs here go to A''s eigenclass end end A.class_eval do #defs here go to A end A.instance_eval do #defs here go to A''s eigenclass end s = "Hello World" class << s #defs here go to s''s eigenclass end

Aquí está la parte del capítulo que habla sobre el tema y es bastante claro sobre el comportamiento.

class_eval y instance_eval se establecen a sí mismos durante la duración del bloque. Sin embargo, difieren en la forma en que configuran el entorno para la definición del método. class_eval configura las cosas como si estuvieras en el cuerpo de una definición de clase, por lo que las definiciones de métodos definirán los métodos de instancia. Por el contrario, llamar a instance_eval en una clase actúa como si estuvieras trabajando dentro de la clase singleton de self. Por lo tanto, cualquier método que defina se convertirá en métodos de clase.

Lo único que creo que vale la pena agregar es que puede llamar a instance_eval en cualquier objeto, no solo en las clases, y el comportamiento no cambia pero tiene diferentes consecuencias.

Algunas lecturas relevantes:

Ruby: instance_eval y definiciones de método class_eval

Capítulo 4 de esta serie más excelente.

Estoy leyendo la sección Metaprogramming de Programming Ruby 1.9 y tengo problemas para entender lo que está pasando internamente entre class_eval / class_exec vs. instance_eval / instance_exec .

En primer lugar, mi entendimiento es que def agrega un método a la tabla de métodos self (el objeto de clase):

class A puts self # => A def foo; 42; end # added to the method table of self, so becomes an instance method end A.new.foo # => 42

Y si usamos class_eval , obtenemos el mismo comportamiento:

A.class_eval do puts self # => A def bar; 42; end # same as above end A.new.bar # => 42

Pero de alguna manera en el caso de instance_eval , las cosas son diferentes:

A.instance_eval do puts self # => A def baz; 42; end # added to the method table of an anonymous # singleton class of self, so becomes a class method end puts A.baz # => 42 s = ''string'' s.instance_eval do ... end # same behavior, so now def creates an instance method

Entonces entiendo la diferencia funcional entre class_eval y instance_eval .

Pero los contextos dentro de los bloques class_eval y instance_eval parecen exactamente iguales, en particular, los puntos local_variables del mismo objeto y las local_variables son las mismas. Entonces, ¿qué está pasando dentro de los bloques (internamente) que hace que def actúe de manera diferente?

¿Hay algún documento que pueda leer? El RDoc para instance_eval y class_eval no ayuda. Mirando la fuente, instance_eval parece configurar un objeto de clase singleton mientras que class_eval no lo hace, pero ¿esta diferencia es visible fuera del código C, en el nivel de Ruby?


Solo para agregar a la respuesta de @krusty.ar: def y define_method agregan métodos al contexto de definición del método actual (creo que así se llama, no estoy seguro), no al self actual.

Es solo que dentro de un módulo, clase o cuerpo de clase de singleton, los dos son los mismos.

Pero, por ejemplo, en un cuerpo de script (también conocido como nivel superior), self es el objeto main , pero el contexto de definición del método actual es Object .