最有用的eval族方法:class_eval

来源:互联网 发布:lol黄金怎么上白金知乎 编辑:程序博客网 时间:2024/05/14 06:50


从本质上讲,class_eval(也就是module_eval)可进入类定义体中:


[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. c=Class.new  
  2. 2 c.class_eval do  
  3. 3    def some_method  
  4. 4        puts "created in class_eval"  
  5. 5    end  
  6. 6 end  
  7. C.new.some_method   => "created in class_eval"  


但是,可以用class_eval做某些class关键字不能做的事:

1.在类定义的上下文中对字符串求值。
2.为匿名类(不包含单例类)打开类定义。
3.获取外围作用域中变量的访问权。
特别是第3个值得注意,如下代码:


[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. var = "init var"  
  2. 2 class C  
  3. 3 puts var  
  4. end    => NameError:undefined local variable or method 'var' for C:Class..  
  5. 5   
  6. 6 C.class_eval {puts var}  
  7. 7        => init var   

变量var在标准的类定义体的作用域之外,但是传递给class_eval的代码块的作用域之内。

当在class_eval的块中定义一个实例方法时,又有所不同:

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. 1 C.class_eval{ def talk; puts var; end }  
  2. 2   
  3. C.new.talk  => undefined loc.'var'..  

和任何def一样,在代码块中的def打开了一个新的作用域-所以变量var成为不可访问的。

如果就是想要把外部作用域的变量硬塞到实例方法中,可以使用另外一个技术来生成方法:define_method方法。

为了在实例方法中访问变量var,可以这么做:


[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. 1 C.class_eval { define_method("talk"){puts var}}  
  2. 2 C.new.talk  
  3. 3     => init  

这样的技术员不会像标准的类和方法定义那样经常地使用,但是在看到它们的时候,就知道它们暗示着一个扁平化的局部变量作用域。而不是像更通用的class和def那样打开新的作用域。
define_method是Module类的实例方法,所以Module或Class的任意实例都可以调用该方法。如果想要在实例方法中访问常规的类定义体中(在此上下文中self是类对象)的局部变量,那么可以在一个通常的类定义体中使用define_method。
0 0
原创粉丝点击