ruby-1.9.2-head :004 > BasicObject.public_methods.select { |x| x =~ /instance_e/ }
=> [:instance_eval, :instance_exec]
eval pero con estas consideraciones:
self durante la evaluación
# Use instance_eval to define class method String.empty
# Note that quotes within quotes get a little tricky...
String.instance_eval("def empty; ''; end")
# Define an instance method len of String to return string length
String.class_eval("def len; size; end")
String.class_eval {
def len
size
end
}
String.class_eval { alias len size }
String.instance_eval { def empty; ""; end }
instance_eval(string [, filename [, lineno]] )
instance_eval {| | block }
En el caso de la String, los dos últimos argumentos
son utilizados para mejorar los mensajes de error
class_eval(string [, filename [, lineno]])
module_eval {|| block }
class Klass
def initialize
@secret = 99
end
end
k = Klass.new
k2 = Klass.new
puts k.instance_eval { @secret } #=> 99
k.instance_eval " def tutu; puts self.inspect; %q{hello}; end"
puts k.tutu # <Klass:0x10016a9f8 @secret=99>
# hello
begin
puts k2.tutu # "tutu" is a singleton method of "k"
rescue NoMethodError
puts $! # undefined method `tutu' for #<Klass:0x10016a958 @secret=99>
end
Klass.instance_eval {
def chachi # A singleton method of a class is a class method!
self.inspect
end
}
puts Klass.chachi # Klass
Los dos últimos argumentos
class_eval(string [, filename [, lineno]])
son utilizados para mejorar los mensajes de error:
~/Chapter8ReflectionandMetaprogramming$ cat -n class_eval.rb
1 class Thing
2 end
3 a = %q{def hello() "Hello there!" end}
4 Thing.module_eval(a)
5 puts Thing.new.hello()
6
7 Thing.module_eval("invalid code",
8 "ficherito.rb", # Fichero del que se leyo el código
9 123 # nº de linea
10 )
Ejecución:
~/Chapter8ReflectionandMetaprogramming$ ruby class_eval.rb Hello there! ficherito.rb:123: undefined local variable or method `code' for Thing:Class (NameError)
Sabemos que podemos crear accessors a los atributos de una clase
usando attr_accessor, attr_reader y attr_writer.
Estas no son palabras reservadas de Ruby sino que se trata de métodos.
Veamos como podemos emular su construcción usando class_eval:
MacBookdeCasiano:chapter8ReflectionandMetaprogramming casiano$ cat -n myAccessors.rb
1 class Module
2 def my_attr_reader(*syms) # método de instancia de Module
3 syms.each { |s| # esto es, ¡un método de clase!
4 class_eval %{ # aquí self es el objeto Module
5 def #{s} # estamos definiendo un método de
6 @#{s} #instancia en la clase "self"
7 end
8 }
9 }
10 end
11 end
12
13 class Chuchu
14 my_attr_reader :a, :b
15
16 def initialize(a,b)
17 @a, @b = a, b
18 end
19 end
20
21 x = Chuchu.new(4, "z")
22 puts x.a # 4
23 puts x.b # z
Casiano Rodriguez León 2015-01-07