objetos - Definir dinĂ¡micamente las clases nombradas en Ruby.
ruby tutorial (3)
Estoy escribiendo un DSL interno en Ruby. Para esto, necesito crear clases nombradas y clases anidadas mediante programación. ¿Cual es la mejor manera de hacerlo? Reconozco que hay dos maneras de hacerlo:
- Use
Class.new
para crear una clase anónima, luego usedefine_method
para agregarle métodos y finalmente llame aconst_set
para agregarlos como constantes con nombre a algún espacio de nombres. - Usa algún tipo de
eval
He probado la primera forma y funcionó, pero como soy nuevo en Ruby, no estoy seguro de que poner las clases como constantes sea la correcta.
¿Hay otras formas mejores? Si no, ¿cuál de los anteriores es preferible?
Deberia ser asi
a_new_class = Class.new(Object) do
attr_accessor :x
def initialize(x)
@x = x
end
end
SomeModule = Module.new
SomeModule.const_set("ClassName", a_new_class)
c = SomeModule::ClassName.new(10)
Realmente no necesitas usar const_set
. El valor de retorno de Class.new
se puede asignar a una constante y el bloque de Class.new
es class_eval
.
class Ancestor; end
SomeClass = Class.new(Ancestor) do
def initialize(var)
print "#{self.class} initialized with #{var}"
end
end
=> SomeClass
SomeClass.new("foo")
# SomeClass initialized with foo=> #<SomeClass:0x668b68>
Si desea crear una clase con un nombre dinámico, tendrá que hacer casi exactamente lo que dijo. Sin embargo, no es necesario utilizar define_method
. Simplemente puede pasar un bloque a Class.new
en el que inicializa la clase. Esto es semánticamente idéntico al contenido de class
/ end
.
Recuerde con const_set
, ser consciente del receptor ( self
) en ese ámbito. Si desea que la clase esté definida globalmente, deberá llamar a const_set
en el módulo TopLevel (que varía en nombre y detalle según Ruby).
a_new_class = Class.new(Object) do
attr_accessor :x
def initialize(x)
print #{self.class} initialized with #{x}"
@x = x
end
end
SomeModule.const_set("ClassName", a_new_class)
c = ClassName.new(10)
...