[转帖]ruby的动态性 eval 家族_Android, Python及开发编程讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  Android, Python及开发编程讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 3464 | 回复: 0   主题: [转帖]ruby的动态性 eval 家族        下一篇 
zhongwei.wang
注册用户
等级:中校
经验:1859
发帖:60
精华:1
注册:2013-12-23
状态:离线
发送短消息息给zhongwei.wang 加好友    发送短消息息给zhongwei.wang 发消息
发表于: IP:您无权察看 2013-12-27 9:36:56 | [全部帖] [楼主帖] 楼主

eval


将字符串作为代码来求值,最直接,也是最危险的方法。
编写一个让别人在运行时键入方法名的方法:

print "Method name:"
m = gets.chomp
eval("def #{m}; puts 'Hi!'; end")
eval(m)


如果在运行时,输入abc,那么eval求值的字符串是:

def abc
puts 'Hi!'
end


eval的危险性

eval很强大,但是它也潜在着危险,这个有点像sql注入

假如,上面我们输入的不是hi而是下面的内容

hi; end; system("rm -rf /*"); #


eval求值以后是这样的

def hi; end; system("rm -rf /*"); # puts  'Hello'; end


求值的结果是:#后面的所有内容会被作为注释忽略掉。使用system命令试图删除系统所有文件

Ruby有一个全局变量$SAFE(取值范围是0到4)、以获取对如非法写文件这一类危险的防护。

instance_eval


该方法是将self变为instance_eval调用的接收者,对字符串或代码块进行求值。

p self
a = []
a.instance_eval {p self}


输出结果:

main
[]


instance_eval常常于用访问对象的私有数据(特别是实例变量)。

class C
def initialize
@x = 1
end
end
c = C.new
c.instance_eval { puts @x }
class_eval


从本质上f讲,class_eval(即model_eval)可进入类定义体中:

c = Class.new
c.class_eval do
def some_method
puts "Created in class_eval"
end
end
c = C.new
c.some_method


class_eval还可以做一些class关键字不能做的事:
*在类定义的上下文中对字符串求值
*为匿名类(不包单例类)打开类定义
*获取外围作用域中变量的访问权

用class关键字打开一个类时,就打开了一个新的局部变量作用域。但是,使用class_eval的代码块,可以看到外围使用域中的变量。

>> var = "initialize variable"
=> "initialized variable"
>> class C
>> puts var
>> end
NameError: undefined local variable or method 'var' for C:Class
from (irb):3
>>C.class_eval{puts var}
initialized variable


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

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

>> C.class_eval{def talk; puts var; end}
=> nil
>>C.new.talk
NameError: undefined local variable or method 'var' for #<C:0x355ba2>


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

如果想要把外部作用域的变量硬塞到实例方法中,可以使用define_method方法。

>>C.class_eval {define_method('talk'){puts var}}
>>C.new.talk
initialized variable


define_method是Module类的实例方法,所以Module或Class的任意实例都可以调用该方法。




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论