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