tutorial objetos modulos manejo lista herencia descargar clases clase ruby metaprogramming dsl metaclass

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:

  1. Use Class.new para crear una clase anónima, luego use define_method para agregarle métodos y finalmente llame a const_set para agregarlos como constantes con nombre a algún espacio de nombres.
  2. 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) ...