Las clases y los módulos son instancias de las clases Class y Module. Por tanto, es posible crearlos dinámicamente:
M = Module.new # Define a new module M C = Class.new # Define a new class C D = Class.new(C) { # Define a subclass of C include M # that includes module M } D.to_s # => "D": class gets constant name by magic
Cuando un módulo o clase dinámicamente creado es asignado a una constante el nombre de esa constante es usado como nombre del módulo o clase.
~/Chapter8ReflectionandMetaprogramming$ cat -n dynamicclassesandmodules.rb 1 Fred = Module.new do 2 def meth1 3 "hello #{args.inspect}" 4 end 5 def meth2 6 "bye #{args.inspect}" 7 end 8 end 9 10 Klass = Class.new do 11 include Fred 12 attr_accessor 'args' 13 14 def initialize(*args) 15 @args = args 16 end 17 end 18 19 puts Fred.to_s # Fred 20 puts Klass.name # Klass 21 22 a = Klass.new(4, 5) 23 24 puts a.meth1 # hello [4, 5] 25 puts a.meth2 # bye [4, 5]
#<Class:0x10016a868>
y name
devolvería nil
.
self
se refiere al mismo objeto
[~/chapter8ReflectionandMetaprogramming]$ cat -n scopegates1.rb 1 v1 = 1 2 puts "%2d"%__LINE__.to_s+' '+local_variables.inspect # [:v1, :obj] 3 4 class Tutu 5 v2 = 2 6 puts "%2d"%(__LINE__.to_s)+' '+local_variables.inspect # [:v2] 7 8 def my_method 9 v3 = 3 10 puts "%2d"%__LINE__.to_s+' '+local_variables.inspect # [:v3] 11 end 12 13 puts "%2d"%__LINE__.to_s+' '+local_variables.inspect # [:v2] 14 end 15 16 obj = Tutu.new 17 obj.my_method 18 obj.my_method 19 puts "%2d"%__LINE__.to_s+' '+local_variables.inspect # [:v1, :obj]Puesto que Class.new, Module.new y define_method usan el bloque que les sigue y los bloques no abandonan el ámbito previo (aunque crean uno nuevo), podemos jugar con estos tres métodos para crear clausuras en las que se comparten variables locales entre clases, métodos y ámbitos. Observe como en esta reescritura del programa anterior cambia la visibilidad:
v1 = 1 Tutu = Class.new do v2 = 2 puts "%2d"%(__LINE__.to_s)+' '+local_variables.inspect # [:v2, :v1, :obj] define_method :my_method do v3 = 3 puts "%2d"%__LINE__.to_s+' '+local_variables.inspect # [:v3, :v2, :v1, :obj] end puts "%2d"%__LINE__.to_s+' '+local_variables.inspect # [:v2, :v1, :obj] end obj = Tutu.new obj.my_method obj.my_method puts "%2d"%__LINE__.to_s+' '+local_variables.inspect # [:v1, :obj]
Casiano Rodriguez León 2015-01-07