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