Pregunta

Soy un iniciador de rubí. Encontré que ambos son bastante similares (en la salida), pero no pude entender la diferencia en el siguiente contexto. Por ejemplo, tengo una clase

class Say
  def self.hello
    puts "hello"
  end
end

y se puede extender así

class << Say
  def hi
    puts "hi"
  end
end

Y también como esto

Say.class_eval do
  def self.bye
    puts "bye"
  end
end

Cuando debo usar << y cuando class_eval?

¿Fue útil?

Solución

class_eval realmente no tiene nada que ver con class << className.

A.class_eval do
   ...
end

es equivalente a

class A
  ...
end

con algunas diferencias. class_eval usa un bloque (o una cadena, pero ignorando eso por el momento), lo que significa que se cierra sobre el alcance léxico que contiene. En otras palabras, puede usar variables locales del alcance circundante. El bloque de clase común presenta un ámbito nuevo. Del mismo modo, puede crear el bloque y pasarlo a muchas class_eval diferentes, y el cuerpo del bloque se ejecutará en el contexto de la clase en la que está llamando class_eval.

class << className abre la clase singleton de className, permitiéndole definir métodos de clase.

class << A
  def foo
    ...
  end
end

Es lo mismo que

def A.foo
  ...
end

Tenga en cuenta que son métodos de clase Oly si es una clase (casi) todos los objetos en Ruby tienen clases de singleton y puede definir métodos para ellos utilizando cualquiera de esas dos sintaxis. La ventaja de class << obj es principalmente si estás definiendo muchos métodos singleton de una vez.

Otros consejos

Como ya se dijo, class_eval realmente no tiene mucho que ver con

class <<self

Incluso si parecen hacer lo mismo en su ejemplo (si bien el efecto es similar, no hace lo mismo, hay diferencias sutiles).

Aquí hay otro ejemplo en el que el uso de la segunda forma es mucho más clara:

class A

end


a = A.new
b = A.new

class <<b
  def say_hi
    puts "Hi !"
  end
end


b.say_hi # will print "Hi !"
a.say_hi # will raise an undefined method

A y B son ambos objetos de la misma clase A, pero agregamos un método a la metaclase de B, por lo que el método Say_hi solo está disponible para el objeto B.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top